This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
YAProlog/dev/yap-6.3/BEAM/eam_am.c

3774 lines
101 KiB
C
Raw Blame History

/*************************************************************************
* *
* 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: eam abstract machine emulator *
* *
* IMPORTANT: ON i386 ISAPPL SHOUD ALWAYS BE AFTER ISVAR *
*************************************************************************/
#ifdef BEAM
#include "Yap.h"
#include "Yatom.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define Debug 0
#define Debug_GC 1
#define Debug_Dump_State 0 /* 0 =off || 1==only on Scheduling || 2== only on GC || 4=on every abs inst NOTE: DEBUG has to be enable to use 4*/
#define Debug_MEMORY 0
#define Memory_Stat 0
#define Clear_MEMORY 0 /* 0- do not clear || 1-> clear on request || 2-> clear on release || 3 -> both*/
#define Fast_go 1 /* normaly 1 ; use 0 to run some extra tests only to control some possible bugs (slower) */
#define USE_SPLIT 1
#define MEM_FOR_BOXES 32 /* In Mb */
#define MEM_FOR_HEAP 32 /* In Mb */
#define MEM_FOR_VARS 32 /* In Mb */
#define MEM_BOXES MEM_FOR_BOXES*1024*1024
#define MEM_H MEM_FOR_HEAP*1024*1024
#define MEM_VARS MEM_FOR_VARS*1024*1024
#define INDEX_SIZE 100000 /* size of vector for saving memory requests */
#define GARBAGE_COLLECTOR 2 /* 0= NO GC || 1 = Heap only || 2 = Heap + Box */
#define HYBRID_BOXMEM 1 /* 0 - Off || 1 - On */
#define START_ON_NEXT 1 /* PLEASE DON'T CHANGE , specially if you use skip_while_var */
#define USE_LEFTMOST 1 /* SHOULD ALWAYS BE 1 for now... */
#define MICRO_TIME 1 /* 0 == eamtime uses CPU time 1 == eamtime uses total time */
#define MAX_MEMORYSTAT 5000
#define READ 0
#define WRITE 1
#include "eam.h"
#include "eamamasm.h"
int EAM=0; /* Is EAM enabled ? */
Cell *beam_ALTERNATIVES; /* NEEDED FOR ABSMI */
PredEntry *bpEntry;
struct EAM_Global EAMGlobal;
struct EAM_Global *eamGlobal=&EAMGlobal;
#if !Debug
#define INLINE inline
#define DIRECT_JUMP 1
#else
#define INLINE
#define DIRECT_JUMP 0
void break_top(void); void break_top(void) { };
void break_debug(int);
void break_debug(int conta) {
#if Debug_Dump_State & 4
dump_eam_state();
#endif
if (Debug!=-1 && conta>Debug*100) {printf("exit por contador>debug\n"); exit(1); }
};
#endif
#define push_mode_and_sreg() { *--beam_sp = (Cell) beam_Mode; *--beam_sp = (Cell) beam_S; }
#define pop_mode_and_sreg() { beam_S = (Cell *) *beam_sp++; beam_Mode = (short) *beam_sp++; }
#define isvar(a) IsVarTerm((Cell) a)
#define isappl(a) IsApplTerm((Cell) a)
#define ispair(a) IsPairTerm((Cell) a)
#define isatom(a) IsAtomOrIntTerm((Cell) a)
#define reppair(a) RepPair((Cell) a)
#define repappl(a) RepAppl((Cell) a)
#define abspair(a) AbsPair((Term *) a)
#define absappl(a) AbsAppl((Term *) a)
int is_perm_var(Cell *a); inline int is_perm_var(Cell *a) { if (a>=(Cell *) beam_END_BOX && a<(Cell *) (beam_END_BOX+MEM_VARS)) return(1); else return (0); }
//int is_perm_var(Cell *a); inline int is_perm_var(Cell *a) { if (a<(Cell *) beam_END_BOX) return(0); else return (1); }
//int is_perm_var(Cell *a); inline int is_perm_var(Cell *a) { if ( a<(Cell *) beam_START_ADDR_HEAP || a>=(Cell *) beam_END_BOX) return(1); else return (0); }
Cell deref(Cell a);
int Unify(Cell *a, Cell *b);
void UnifyCells(Cell *a, Cell *b);
void trail(struct AND_BOX *andbox,struct PERM_VAR *a);
void limpa_trail(struct AND_BOX *andbox);
void get_arguments(int nr, Cell *a);
Cell *save_arguments(int nr);
void remove_memory_arguments(Cell *a);
void initialize_memory_areas(void);
Cell *request_memory(int size);
void free_memory(Cell *mem,int size);
void limpa_trail_orbox(struct OR_BOX *orbox);
struct SUSPENSIONS *addto_suspensions_list(struct AND_BOX *a,int reason);
void delfrom_suspensions_list(struct SUSPENSIONS *b);
void totop_suspensions_list(struct SUSPENSIONS *b);
int verify_externals(struct AND_BOX *and_box);
void remove_from_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox);
void change_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox,struct AND_BOX *new);
void do_forking_andbox(struct AND_BOX *a);
void remove_all_externals(struct AND_BOX *andbox);
void remove_all_externals_suspensions(struct AND_BOX *andbox);
void del_andbox_and_sons(struct AND_BOX *andbox);
void del_orbox_and_sons(struct OR_BOX *orbox);
void waking_boxes_suspended_on_var(struct PERM_VAR *v);
struct PERM_VAR *request_permVar(struct AND_BOX *a);
void free_permVar(struct PERM_VAR *v);
Cell *request_memory_locals(int nr);
Cell *request_memory_locals_noinit(int nr);
void free_memory_locals(Cell *l);
void add_to_list_perms(struct PERM_VAR *var,struct AND_BOX *a);
void remove_list_perms(struct AND_BOX *a);
void move_perm_vars(struct AND_BOX *b, struct AND_BOX *a);
void move_perm_variables(struct AND_BOX *a);
void inc_level(struct AND_BOX *andbox,int dif);
void abort_eam(char *s);
void exit_eam(char *s);
int HEAP_MEM_FULL(void);
void change_from_to(struct PERM_VAR *o,struct PERM_VAR *d);
unsigned int index_of_hash_table_atom(Cell c, int nr);
unsigned int index_of_hash_table_appl(Cell c, int nr);
int deve_limpar_var(struct EXTERNAL_VAR *e);
struct status_and *remove_call_from_andbox(struct status_and *ncall, struct AND_BOX *a);
int is_leftmost(struct AND_BOX *a, struct status_and *n);
int exists_var_in(Cell *c);
void garbage_collector(void);
void conta_memoria_livre(int size);
int showTime(void);
struct AND_BOX *choose_leftmost(void);
extern Cell BEAM_is(void);
extern void do_eam_indexing(struct Predicates *);
extern void Yap_plwrite(Term, struct stream_desc *, int, int);
#if Debug_Dump_State
void dump_eam_state(void);
#endif
/************************************************************************\
* Debug + Status routines *
\************************************************************************/
void conta_memoria_livre(int size){
int i,nr,ult=0;
long total=0;
Cell *c;
for(i=0;i<INDEX_SIZE;i++) {
nr=0;
c=beam_IndexFree[i];
while(c!=NULL) {
ult=i;
nr++;
c=(Cell *) *c;
}
total=total+nr*i;
}
printf("Ultimo Pedido (bytes) =%d <20> Ultimo bloco livre=%d\n",size,(int) ult*CELL_SIZE);
printf("Memoria TOTAL (bytes) =%ld \n",((unsigned long) beam_END_BOX)-((unsigned long) beam_START_ADDR_BOXES));
printf("Memoria livre no IndexFree=%ld \n",total*CELL_SIZE);
printf("Memoria Total livre =%ld \n",total*CELL_SIZE+((unsigned long) beam_END_BOX)-((unsigned long)beam_NextFree));
printf("Memoria Total na HEAP=%ld livre=%ld \n",(unsigned long) MEM_H,(unsigned long) beam_H-(unsigned long) beam_START_ADDR_HEAP);
}
void abort_eam(char *s)
{
printf("%s\n",s);
exit(1);
}
void exit_eam(char *s)
{
printf("%s\n",s);
if (beam_nr_call_forking) printf("%d forks executed\n",beam_nr_call_forking);
if (beam_nr_gc_heap)
printf("GC was called %d times on Heap Mem\n",beam_nr_gc_heap);
if (beam_nr_gc_boxed)
printf("GC was called %d times on Boxed Mem\n",beam_nr_gc_boxed);
if (beam_nr_gc_boxed && beam_nr_gc_heap)
printf("GC was called %d times \n",beam_nr_gc_boxed+beam_nr_gc_heap);
#if Memory_Stat
{unsigned long req, used;
req=beam_TOTAL_MEM+beam_TOTAL_PERMS;
used=(beam_TOTAL_MEM+beam_TOTAL_PERMS)-(beam_MEM_REUSED+beam_PERMS_REUSED);
printf("-------------------------------------------------------------------\n");
printf("Total Mem: Requested %ld (%.2fKb) (%.2fMb) \n", req, req/1024.0, req/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used,used/1024.0, used/1048576.0, (float) (req-used)/req*100,'%');
printf("-------------------------------------------------------------------\n");
used=(beam_TOTAL_MEM-beam_TOTAL_TEMPS)-(beam_MEM_REUSED-beam_TEMPS_REUSED);
printf("Boxed Mem: Requested %ld (%.2fKb) (%.2fMb) \n", beam_TOTAL_MEM-beam_TOTAL_TEMPS, (beam_TOTAL_MEM-beam_TOTAL_TEMPS)/1024.0, (beam_TOTAL_MEM-beam_TOTAL_TEMPS)/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used, used/1024.0, used/1048576.0, (float) (beam_MEM_REUSED-beam_TEMPS_REUSED)/(beam_TOTAL_MEM-beam_TOTAL_TEMPS)*100,'%');
used=beam_TOTAL_TEMPS-beam_TEMPS_REUSED;
printf("Temps Mem: Requested %ld (%.2fKb) (%.2fMB)\n", beam_TOTAL_TEMPS, beam_TOTAL_TEMPS/1024.0, beam_TOTAL_TEMPS/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used, used/1024.0,used/1048576.0,(float) beam_TEMPS_REUSED/(beam_TOTAL_TEMPS)*100,'%');
used=beam_TOTAL_PERMS-beam_PERMS_REUSED;
printf("Perms Mem: Requested %ld (%.2fKb) (%.2fMB)\n", beam_TOTAL_PERMS, beam_TOTAL_PERMS/1024.0, beam_TOTAL_PERMS/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used, used/1024.0,used/1048576.0,(float) beam_PERMS_REUSED/(beam_TOTAL_PERMS)*100,'%');
}
printf("-------------------------------------------------------------------\n");
if (beam_nr_gc_boxed+beam_nr_gc_heap>0) {
int i;
beam_Memory_STAT[0][0]=0; beam_Memory_STAT[0][1]=0; beam_Memory_STAT[0][2]=0; beam_Memory_STAT[0][3]=0; beam_Memory_STAT[0][4]=0;
for(i=1;i<=beam_nr_gc_boxed+beam_nr_gc_heap;i++) {
beam_Memory_STAT[0][0]+=beam_Memory_STAT[i][0];
beam_Memory_STAT[0][1]+=beam_Memory_STAT[i][1];
beam_Memory_STAT[0][2]+=beam_Memory_STAT[i][2];
beam_Memory_STAT[0][3]+=beam_Memory_STAT[i][3];
beam_Memory_STAT[0][4]+=beam_Memory_STAT[i][4];
printf("GC %4d Time=%ld H=%ld to %ld (%3.2f) Box=%ld to %ld (%3.2f)\n",
i, beam_Memory_STAT[i][0], beam_Memory_STAT[i][1], beam_Memory_STAT[i][3],
((float) beam_Memory_STAT[i][3]/beam_Memory_STAT[i][1])*100 , beam_Memory_STAT[i][2], beam_Memory_STAT[i][4],
((float) beam_Memory_STAT[i][4]/beam_Memory_STAT[i][2])*100);
}
i--;
printf("\nRESUME GC: Time=%ld H=%ld to %ld (%3.2f) Box=%ld to %ld (%3.2f)\n",
beam_Memory_STAT[0][0]/i, beam_Memory_STAT[0][1]/i, beam_Memory_STAT[0][3]/i,
100.0-((float) beam_Memory_STAT[0][3]/beam_Memory_STAT[0][1])*100 , beam_Memory_STAT[0][2]/i, beam_Memory_STAT[0][4]/i,
100.0-((float) beam_Memory_STAT[0][4]/beam_Memory_STAT[0][2])*100);
} else {
printf("Heap Mem Requested %ld (%.2fKb) (%.2fMB) \n", ((unsigned long) beam_H-beam_START_ADDR_HEAP), ((unsigned long) beam_H-beam_START_ADDR_HEAP)/1024.0, ((unsigned long) beam_H-beam_START_ADDR_HEAP)/1048576.0);
printf("-------------------------------------------------------------------\n");
}
#endif
exit(0);
}
/************************************************************************\
* Memory Management routines *
\************************************************************************/
void initialize_memory_areas()
{
static int first_time=1;
if (first_time) {
first_time=0;
beam_IndexFree=(Cell **) malloc(INDEX_SIZE*POINTER_SIZE);
if ((void *) beam_IndexFree==(void *)NULL) abort_eam("Memory Initialization Error IndexFree\n");
beam_START_ADDR_HEAP=(unsigned long) malloc(MEM_H+MEM_BOXES+MEM_VARS);
if ((void *)beam_START_ADDR_HEAP==(void *)NULL) abort_eam("Memory Initialization Error Heap+Boxes\n");
beam_START_ADDR_BOXES=beam_START_ADDR_HEAP+MEM_H;
beam_END_H=beam_START_ADDR_HEAP+MEM_H;
beam_END_BOX=beam_START_ADDR_BOXES+MEM_BOXES;
}
beam_sp=(Cell *) beam_END_H; beam_sp-=2;
beam_NextVar=(struct PERM_VAR *) beam_END_BOX;
beam_H=(Cell *) beam_START_ADDR_HEAP;
#if GARBAGE_COLLECTOR!=2
beam_NextFree=(Cell *) beam_END_BOX;
#else
beam_NextFree=(Cell *) beam_START_ADDR_BOXES;
#endif
beam_MemGoing=1;
memset(beam_IndexFree,0,INDEX_SIZE*POINTER_SIZE);
{ int i,max;
max=MEM_VARS/PERM_VAR_SIZE;
for(i=0;i<max-1;i++) {
beam_NextVar[i].next=&beam_NextVar[i+1];
}
beam_NextVar[max-1].next=NULL;
}
beam_varlocals=NULL;
beam_USE_SAME_ANDBOX=NULL;
beam_nr_alternative=NULL;
beam_nr_call=NULL;
beam_nr_gc_heap=0;
beam_nr_gc_boxed=0;
beam_Mode=READ;
beam_VAR_TRAIL_NR=0;
beam_nr_call_forking=0;
beam_Mem_FULL=0;
#if Memory_Stat
beam_TOTAL_MEM=0; beam_MEM_REUSED=0; beam_TOTAL_TEMPS=0; beam_TEMPS_REUSED=0; beam_TOTAL_PERMS=0; beam_PERMS_REUSED=0;
memset(beam_Memory_STAT,0,MAX_MEMORYSTAT*5*sizeof(unsigned long));
#endif
}
INLINE int HEAP_MEM_FULL(void)
{
if (beam_MemGoing==1) {
if ((unsigned long)beam_H>(unsigned long)(beam_START_ADDR_HEAP+MEM_H/2)) {
beam_Mem_FULL|=2;
}
} else {
if ((unsigned long) beam_H>(unsigned long)(beam_START_ADDR_HEAP+MEM_H)) {
beam_Mem_FULL|=2;
}
}
return(beam_Mem_FULL);
}
INLINE Cell *request_memory(int size) /* size in bytes */
{
register Cell *mem;
register int size_cells;
if (size==0) return NULL;
size_cells=size/CELL_SIZE;
#if !Fast_go
if (size_cells> INDEX_SIZE)
abort_eam("Foi pedido um block de memoria grande demais !!! \n");
#endif
#if Debug & Debug_MEMORY
printf("Requesting memory size %d\n",size_cells);
#endif
#if HYBRID_BOXMEM
mem=beam_IndexFree[(unsigned) size_cells];
#if Memory_Stat
beam_TOTAL_MEM+=size;
if (mem!=NULL) beam_MEM_REUSED+=size;
#endif
if (mem==NULL) {
#else /* GC Only */
#if Memory_Stat
beam_TOTAL_MEM+=size;
#endif
if (1) {
#endif
#if GARBAGE_COLLECTOR!=2
beam_NextFree-=size_cells;
mem=beam_NextFree;
if (beam_NextFree< (Cell *) beam_START_ADDR_BOXES) abort_eam("No more BOX_MEM \n");
#else
if (beam_MemGoing==1) {
mem=beam_NextFree;
beam_NextFree+=size_cells;
if (beam_NextFree> (Cell *) ( beam_START_ADDR_BOXES+MEM_BOXES/2)) beam_Mem_FULL |= 1;
} else {
beam_NextFree-=size_cells;
mem=beam_NextFree;
if (beam_NextFree< (Cell *) ( beam_START_ADDR_BOXES+MEM_BOXES/2)) beam_Mem_FULL |=1;
}
#endif
} else {
beam_IndexFree[(unsigned) size_cells]=(Cell *) *mem;
}
#if Clear_MEMORY & 1
memset(mem,0,size); /* NOT REALLY NECESSARY, use only to detect possible errors*/
#endif
return(mem);
}
#if HYBRID_BOXMEM==0
void free_memory(Cell *mem,int size) {
#if Clear_MEMORY & 2
memset(mem,0,size);
#endif
};
#else
INLINE void free_memory(Cell *mem,int size) /* size in bytes */
{
register int size_cells;
if (size==0 || mem==NULL) return;
size_cells=size/CELL_SIZE;
#if Clear_MEMORY & 2
memset(mem,0,size); /* NOT REALLY NECESSARY, use only to detect possible errors*/
#endif
#if Debug & Debug_MEMORY
printf("Freeing memory size %d\n",size_cells);
#endif
*mem=(Cell) beam_IndexFree[size_cells];
beam_IndexFree[size_cells]=mem;
}
#endif
INLINE void get_arguments(int nr, Cell *a)
{
register int i;
for(i=1;i<=nr;i++) beam_X[i]=a[i];
}
INLINE Cell *save_arguments(int nr) /* nr arguments */
{
if (!nr) return(NULL);
{
register int i;
register Cell *a;
a=(Cell *)request_memory((nr+1)*CELL_SIZE);
a[0]=nr+1;
for(i=1;i<=nr;i++) a[i]=beam_X[i];
return(a);
}
}
INLINE void remove_memory_arguments(Cell *a)
{
if (a==NULL) return;
#if !Fast_go
if (a[0]<1 || a[0]>1000)
printf("%d Numero Invalido de Argumentos............\n",a[0]);
#endif
free_memory(a,a[0]*CELL_SIZE);
}
struct PERM_VAR *request_permVar(struct AND_BOX *a) {
struct PERM_VAR *pv;
#if Memory_Stat
static struct PERM_VAR *old=NULL;
beam_TOTAL_PERMS+=PERM_VAR_SIZE;
if (old<=beam_NextVar) old=beam_NextVar;
else beam_PERMS_REUSED+=PERM_VAR_SIZE;
#endif
#if Debug && Debug_MEMORY
printf("Requesting a permVar...\n");
#endif
#if !Fast_go
if (beam_NextVar->next==NULL) { printf("Fim da memoria para variaveis\n"); exit (-1); }
#endif
pv=beam_NextVar;
beam_NextVar=beam_NextVar->next;
pv->value=(Cell) &(pv->value);
pv->home=a;
pv->suspensions=NULL;
pv->yapvar=NULL;
pv->next=a->perms;
a->perms=pv;
return (pv);
}
void free_permVar(struct PERM_VAR *v) {
#if Clear_MEMORY
v->value=(Cell) NULL;
v->home=(struct AND_BOX *) NULL;
v->suspensions=(struct SUSPENSIONS_VAR *) NULL;
#endif
#if Debug & Debug_MEMORY
printf("Freeing a permVar...\n");
#endif
v->next=beam_NextVar;
beam_NextVar=v;
return;
}
INLINE Cell *request_memory_locals(int nr)
{
Cell *l;
int i;
#if Memory_Stat
Cell *old;
old=beam_NextFree;
beam_TOTAL_TEMPS+=CELL_SIZE*(nr+1);
#endif
#if Debug_MEMORY
printf("Requesting Memory for %d+1 locals...\n",nr);
#endif
l=(Cell *)request_memory(CELL_SIZE*(nr+1));
l[0]=nr;
l++;
for(i=0;i<nr;i++) {
l[i]=(Cell) &l[i];
}
#if Memory_Stat
if (old==beam_NextFree) beam_TEMPS_REUSED+=CELL_SIZE*(nr+1);
#endif
return(l);
}
INLINE Cell *request_memory_locals_noinit(int nr)
{
Cell *l;
#if Memory_Stat
Cell *old;
old=beam_NextFree;
beam_TOTAL_TEMPS+=CELL_SIZE*(nr+1);
#endif
#if Debug_MEMORY
printf("Requesting Memory for %d+1 locals (not initialized)...\n",nr);
#endif
l=(Cell *)request_memory(CELL_SIZE*(nr+1));
l[0]=nr;
l++;
#if Memory_Stat
if (old==beam_NextFree) beam_TEMPS_REUSED+=CELL_SIZE*(nr+1);
#endif
return(l);
}
INLINE void free_memory_locals(Cell *l)
{
if (l==NULL || l[-1]==0) return;
#if Debug_MEMORY
printf("Freeing Memory for %ld+1 locals...\n",l[-1]);
#endif
free_memory((Cell *) &l[-1], CELL_SIZE*(l[-1]+1));
l[-1]=0; /* <20> necess<73>rio para evitar apagar este vector novamente
porque varias calls podem estar a referenciar o mesmo vector locals */
}
/************************************************************************\
* Manipulating And-Or-Boxes structures *
\************************************************************************/
void del_andbox_and_sons(struct AND_BOX *andbox )
{
register struct status_and *ncall;
if (andbox==NULL) return;
remove_all_externals(andbox);
delfrom_suspensions_list(andbox->suspended);
ncall=andbox->calls;
while(ncall!=NULL) {
del_orbox_and_sons(ncall->call);
{
struct status_and *ncall_old;
ncall_old=ncall;
ncall=ncall->next;
free_memory_locals(ncall_old->locals);
free_memory((Cell *) ncall_old,STATUS_AND_SIZE);
}
}
remove_list_perms(andbox);
free_memory((Cell *) andbox,ANDBOX_SIZE);
}
void del_orbox_and_sons(struct OR_BOX *orbox)
{
struct status_or *so;
Cell *a=NULL;
if (orbox==NULL) return;
so=orbox->alternatives;
while (so!=NULL) {
struct status_or *old;
del_andbox_and_sons(so->alternative);
a=so->args;
old=so;
so=so->next;
free_memory((Cell *) old,STATUS_OR_SIZE);
}
remove_memory_arguments(a); /* remove args */
free_memory((Cell *) orbox,ORBOX_SIZE);
}
INLINE struct status_and *remove_call_from_andbox(struct status_and *ncall, struct AND_BOX *a)
{
register int nr;
struct status_and *r;
nr=a->nr_all_calls;
nr--;
a->nr_all_calls=nr;
if (nr==0) {
a->calls=NULL;
} else {
if (ncall->previous!=NULL) {
ncall->previous->next=ncall->next;
} else a->calls=ncall->next;
if (ncall->next!=NULL) {
ncall->next->previous=ncall->previous;
}
}
r=ncall->next;
{ /* vou ver se as locals ainda estao a ser usadas por outra ncall */
int aSerUsada=0;
struct status_and *l;
l=ncall->previous;
while (l!=NULL) {
if (l->locals==ncall->locals) { aSerUsada=1; break; }
l=l->previous;
}
l=r;
while (aSerUsada==0 && l!=NULL) {
if (l->locals==ncall->locals) { aSerUsada=1; break; }
l=l->next;
}
// aSerUsada=1; /* CUIDADO ao apagar as var locals da call */
if (aSerUsada==0) free_memory_locals(ncall->locals);
}
free_memory((Cell *) ncall,STATUS_AND_SIZE);
return(r);
}
INLINE void totop_suspensions_list(struct SUSPENSIONS *b)
{
if (beam_su==b) return; /* is already on top of list */
if (beam_su->prev==b) { beam_su=b; return; } /* It was the last one */
b->prev->next=b->next;
b->next->prev=b->prev;
b->next=beam_su;
b->prev=beam_su->prev;
beam_su->prev=b;
b->prev->next=b;
beam_su=b;
}
void waking_boxes_suspended_on_var(struct PERM_VAR *v)
{
struct SUSPENSIONS_VAR *s;
s=v->suspensions;
while(s!=NULL) {
register struct AND_BOX *a;
#if Debug
printf("Waking and_box assigment changed on a var that forced and_box to suspend \n");
#endif
a=s->and_box;
totop_suspensions_list(a->suspended);
a->nr_alternative->state|=WAKE;
s=s->next;
}
}
/* THE FALLOWING ROTINES ARE TO BE APPLYED TO THE SUSPENSION LIST
(DO NOT USE IT TO THE SUSPENSIONS ON THE LOCAL_VAR) */
INLINE struct SUSPENSIONS *addto_suspensions_list(struct AND_BOX *a,int r)
{
struct SUSPENSIONS *s;
if (a->suspended) return(a->suspended); /* already suspended */
s=(struct SUSPENSIONS *) request_memory(SUSPENSIONS_SIZE);
s->and_box=a;
s->reason=r;
if (beam_su==NULL) {
s->next=s;
s->prev=s;
beam_su=s;
} else {
s->next=beam_su;
s->prev=beam_su->prev;
beam_su->prev=s;
if (beam_su->next==beam_su) { /* so existem 2 elementos na lista */
beam_su->next=s;
} else {
s->prev->next=s;
}
}
return(s);
}
void delfrom_suspensions_list(struct SUSPENSIONS *b)
{
if (b==NULL) return;
#if !Fast_go
if ( b->and_box->suspended==NULL)
abort_eam("Nunca deveria acontecer no delfrom_suspensions_list ?????\n");
#endif
remove_all_externals_suspensions(b->and_box);
b->and_box->suspended=NULL;
if (b==beam_su) beam_su=b->next;
if (b==beam_su) { /* so existe um */
beam_su=NULL;
} else {
b->prev->next=b->next;
b->next->prev=b->prev;
}
free_memory((Cell *) b,SUSPENSIONS_SIZE);
}
INLINE void change_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox,struct AND_BOX *new)
{
struct SUSPENSIONS_VAR *s;
s=v->suspensions;
while(s!=NULL)
{
if (s->and_box==andbox) {
s->and_box=new;
return;
}
s=s->next;
}
}
/* MANIPULATE PERM VARS SUSPENSIONS */
INLINE void remove_from_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox)
{
struct SUSPENSIONS_VAR *s,*prev=NULL;
if (v==NULL) {
#if !Fast_go
abort_eam("Nunca deveria acontecer no remove_from_perm_var_suspensions ?????\n");
#endif
return;
}
s=v->suspensions;
while(s!=NULL)
{
struct SUSPENSIONS_VAR *next;
next=s->next;
if (s->and_box==andbox) {
if (prev==NULL) {
v->suspensions=s->next;
} else prev->next=s->next;
free_memory((Cell *) s,SUSPENSIONS_VAR_SIZE);
} else { /* acordar as boxes restantes porque houve uma alteracao */
s->and_box->nr_alternative->state |=WAKE;
prev=s;
}
s=next;
}
}
void remove_all_externals_suspensions(struct AND_BOX *andbox)
{
struct EXTERNAL_VAR *e;
e=andbox->externals;
while(e) {
remove_from_perm_var_suspensions(e->var,andbox);
e=e->next;
}
}
void remove_all_externals(struct AND_BOX *andbox)
{
struct EXTERNAL_VAR *e;
e=andbox->externals;
while(e) {
struct EXTERNAL_VAR *next;
next=e->next;
remove_from_perm_var_suspensions(e->var,andbox);
free_memory((Cell *)e,EXTERNAL_VAR_SIZE);
e=next;
}
}
void remove_list_perms(struct AND_BOX *a)
{
struct PERM_VAR *l,*oldl;
l=a->perms;
a->perms=NULL;
while(l) {
oldl=l;
l=oldl->next;
free_permVar(oldl);
}
}
INLINE void move_perm_vars(struct AND_BOX *b, struct AND_BOX *a) /* (from b to a) */
{
struct PERM_VAR *l,*old;
l=b->perms;
if (l==NULL) return;
do {
old=l;
l->home=a;
if (l->suspensions) change_perm_var_suspensions(l,b,a);
l=l->next;
} while(l!=NULL);
old->next=a->perms;
a->perms=b->perms;
return;
}
void add_to_list_perms(struct PERM_VAR *var,struct AND_BOX *a)
{
var->next=a->perms;
a->perms=var;
return;
}
/* change all suspended external references of perm var o to perm var d */
void change_from_to(struct PERM_VAR *o,struct PERM_VAR *d) {
struct SUSPENSIONS_VAR *s,*last;
#if Debug
printf("Change Vars from one andbox to another\n");
#endif
s=o->suspensions;
if (s==NULL) return;
/* CUIDADO - Don't Forget to Write de Code to verify if they are compatible */
/* second change the references of o to point to d, also change suspensions from o to d */
do {
struct EXTERNAL_VAR *e;
#if Debug
struct SUSPENSIONS_VAR *l;
l=d->suspensions;
while(l!=NULL) {
if (l->and_box==s->and_box) {
printf("Same and-box binding... must check for compatibility.......!!!!");
}
l=l->next;
}
#endif
e=s->and_box->externals;
while(e!=NULL) {
if (e->var==o) {
e->var=d;
}
e=e->next;
}
last=s;
s=s->next;
} while(s);
last->next=d->suspensions;
d->suspensions=o->suspensions;
o->suspensions=NULL;
}
/************************************************************************\
* Other routines *
\************************************************************************/
void inc_level(struct AND_BOX *andbox,int dif)
{
struct OR_BOX *orbox;
struct status_and *calls;
if (andbox==NULL) return;
andbox->level+=dif;
calls=andbox->calls;
while(calls!=NULL) {
orbox=calls->call;
if (orbox!=NULL) {
struct status_or *so;
so=orbox->alternatives;
while (so!=NULL) {
inc_level(so->alternative,dif);
so=so->next;
}
}
calls=calls->next;
}
}
INLINE int is_leftmost(struct AND_BOX *a, struct status_and *n)
{
if (a==beam_top) return(1);
if (a->calls!=n) return(0);
if (a->nr_alternative->previous!=NULL) return(0);
return(is_leftmost(a->parent->parent,a->parent->nr_call));
}
struct AND_BOX *choose_leftmost(void)
{
struct AND_BOX *a;
struct OR_BOX *o=NULL;
struct status_and *ncall;
a=beam_top;
do {
ncall=a->calls;
if (ncall==NULL) break;
while(ncall!=NULL) {
o=ncall->call;
if (o!=NULL) break;
ncall=ncall->next;
}
if (ncall==NULL) break;
a=o->alternatives->alternative;
if (a==NULL) { beam_OBX=o; return(a); }
} while(1);
return a;
}
INLINE unsigned int index_of_hash_table_atom(Cell c, int nr)
{
return (((unsigned long) c >>3) % nr);
}
INLINE unsigned int index_of_hash_table_appl(Cell c, int nr)
{
return (((unsigned long) c >>5) % nr);
}
/************************************************************************\
* Unification routines *
\************************************************************************/
void trail(struct AND_BOX *andbox,struct PERM_VAR *v)
{
register struct EXTERNAL_VAR *e;
int var_level;
if (!is_perm_var((Cell *) v)) return;
var_level=(v->home)->level;
if (var_level>=andbox->level) { /* Don't Need to Trail */
waking_boxes_suspended_on_var(v); /* Really Not Needed, just to speedup avoiding forks */
if (isvar(v->value)) { /* CUIDADO posso ter de fazer deref primeiro */
change_from_to(v,(struct PERM_VAR *) *((Cell *) v->value));
}
return;
}
#if Debug
printf("Trailing var 0x%lX on ANDBOX 0x%lX\n", (unsigned long) v, (unsigned long) andbox);
#endif
e=(struct EXTERNAL_VAR *) request_memory(EXTERNAL_VAR_SIZE);
e->next=andbox->externals;
andbox->externals=e;
e->var=v;
e->value=v->value;
}
INLINE int deve_limpar_var(struct EXTERNAL_VAR *e)
{
return(e->var->value==e->value && isvar(e->var) ); /* ????? */
}
void limpa_trail(struct AND_BOX *andbox)
{
struct EXTERNAL_VAR *e;
Cell *l;
if (andbox==NULL) return;
e=andbox->externals;
while(e!=NULL) {
if (deve_limpar_var(e)) {
l=(Cell *) e->var;
*((Cell *) l)=(Cell) l;
}
e=e->next;
}
{ register struct status_and *ncall;
ncall=andbox->calls;
while(ncall) {
register struct OR_BOX *o;
o=ncall->call;
if (o!=NULL) {
struct status_or *so;
so=o->alternatives;
while (so!=NULL) {
limpa_trail(so->alternative);
so=so->next;
}
}
ncall=ncall->next;
}
}
}
INLINE void limpa_trail_orbox(struct OR_BOX *orbox)
{
struct status_or *so;
so=orbox->alternatives;
while(so!=NULL) {
limpa_trail(so->alternative);
so=so->next;
}
}
INLINE Cell deref(Cell a)
{
register Cell *b;
while(isvar(a)) {
b = (Cell *) a;
a = *b;
if(a==((Cell) b)) return a;
}
return a;
}
void UnifyCells(Cell *a, Cell *b) /* a e b variaveis */
{
if(a==b) return;
if (is_perm_var(a)) {
if (is_perm_var(b)) {
register int i,j;
i=((struct PERM_VAR *) a)->home->level;
j=((struct PERM_VAR *) b)->home->level;
if (i<j) {
*b=(Cell) a;
trail(beam_ABX,(struct PERM_VAR *) b);
return;
} else {
*a=(Cell) b;
trail(beam_ABX,(struct PERM_VAR *) a);
return;
}
} else {
*b=(Cell) a;
return;
}
}
*a=(Cell) b;
return;
}
int Unify(Cell *a, Cell *b)
{
a = (Cell *) deref((Cell) a);
b = (Cell *) deref((Cell) b);
if(isvar(a)) {
if(isvar(b)) {
UnifyCells(a,b);
return 1;
}
{ *a=(Cell) b; trail(beam_ABX,(struct PERM_VAR *)a); }
return 1;
}
if(isvar(b)) {
{ *b=(Cell) a; trail(beam_ABX,(struct PERM_VAR *)b); }
return 1;
}
if(a==b) return 1;
if(isappl(a)) {
int arity;
if(!isappl(b)) return 0;
a = (Cell *) repappl(a);
b = (Cell *) repappl(b);
if(*a != *b) return 0;
arity = ((int) ArityOfFunctor((Functor) *a));
while(arity!=0) {
if(!Unify((Cell *)a[arity], (Cell *)b[arity])) return 0;
--arity;
}
return 1;
}
if(ispair(a)) {
if(!ispair(b)) return 0;
a = (Cell *) reppair(a);
b = (Cell *) reppair(b);
if(!Unify((Cell *)*a,(Cell *)*b)) return 0;
return Unify((Cell *)a[1],(Cell *) b[1]);
}
if(a!=b) return 0;
return 1;
}
int verify_externals(struct AND_BOX *andbox)
{
struct EXTERNAL_VAR *e,*prev;
#if Debug
printf("Entering Verify Externals \n");
#endif
e=andbox->externals;
prev=NULL;
while(e) {
Cell d;
d=deref((Cell) e->var); /* e->var->value */
if (!isvar(d)) { /* ja nao e' var */
if (isvar(e->value)) {
struct PERM_VAR *old,*new;
struct SUSPENSIONS_VAR *s;
old=e->var;
new=(struct PERM_VAR *) e->value;
e->var=new;
e->value=(Cell) old;
remove_from_perm_var_suspensions(old,andbox);
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE);
s->and_box=andbox;
s->next=new->suspensions;
new->suspensions=s;
if (e->var->home->level==andbox->level) { /* ja nao e' uma var externa */
e->var->value=e->value;
goto tudo_ok;
}
prev=e;
e=e->next;
continue;
} else {
if (Unify((Cell *) d,(Cell *) e->value)) {
/* Preciso de ter cuidado pois podem ter sido criadas External Vars */
if (prev==NULL && andbox->externals!=e) {
prev=andbox->externals;
while (prev->next!=e) prev=prev->next;
}
goto tudo_ok;
}
#if Debug
printf("Verify Externals Has failed \n");
#endif
return(0);
}
} else { /* ainda e' var */
if (e->var->home->level==andbox->level) { /* ja nao e' uma var externa */
/* e->var->value=e->value; */
*((Cell *) d)=e->value;
tudo_ok:
/* primeiro remover a andbox da lista de suspensoes da variavel */
remove_from_perm_var_suspensions(e->var,andbox);
waking_boxes_suspended_on_var(e->var);
/* remover a variavel da lista de externals */
if (prev==NULL) { /* a var e' a primeira da lista */
andbox->externals=e->next;
free_memory((Cell *)e,EXTERNAL_VAR_SIZE);
e=andbox->externals;
continue;
} else {
prev->next=e->next;
free_memory((Cell *)e,EXTERNAL_VAR_SIZE);
e=prev->next;
continue;
}
}
}
prev=e;
e=e->next;
}
if (andbox->externals==NULL) { /* Se ja nao ha external vars posso remover andbox da lista suspensions */
delfrom_suspensions_list(andbox->suspended);
}
#if Debug
printf("Verify Externals Has ended with Sucess\n");
#endif
return(1); /* Means OK */
}
int exists_var_in(Cell *c)
{
Cell *C, *OldC;
OldC=(Cell *) deref((Cell) c);
if (isvar(OldC)) {
return(1);
}
if (isatom(OldC)) {
return(0);
}
if (ispair(OldC)) {
C=(Cell *) reppair(OldC);
return(exists_var_in(C) || exists_var_in(++C));
}
return(0);
}
/************************************************************************\
* Emulador de EAM *
\************************************************************************/
void give_solution_toyap(void);
void give_solution_toyap(void) {
struct PERM_VAR *l;
l=beam_ABX->perms;
while(l) {
if (l->yapvar) {
*TR=(Cell) l->yapvar;
TR++;
*(l->yapvar)=l->value;
}
l=l->next;
}
}
void add_vars_to_listperms(struct AND_BOX *a, Cell *arg);
void add_vars_to_listperms(struct AND_BOX *a, Cell *arg) {
Cell *_DR;
Cell *NewC;
_DR=(Cell *) deref((Cell) arg);
if (isvar((Cell *) _DR) && !is_perm_var(_DR)) {
struct PERM_VAR *l;
l=request_permVar(a);
l->yapvar=_DR;
*_DR=(Cell) l;
}
if (isappl(_DR)) {
int i,arity;
NewC=(Cell *) repappl(_DR);
arity = ((int) ArityOfFunctor((Functor) *NewC));
for(i=0;i<arity ;i++) {
NewC++;
add_vars_to_listperms(a,NewC);
}
}
if (ispair(_DR)) {
NewC=(Cell *) reppair(_DR);
add_vars_to_listperms(a,NewC);
NewC++;
add_vars_to_listperms(a,NewC);
NewC++;
}
/* <20> atomic, posso terminar */
}
PredEntry *prepare_args_torun(void);
PredEntry *prepare_args_torun(void) {
Cell *_DR;
Prop pe;
PredEntry *ppe;
/* at this time, ARG1=call */
_DR=(Cell *) deref(beam_X[1]);
if (isatom(_DR)) {
/* char *name = AtomOfTerm((Term) _DR)->StrOfAE; */
pe = PredPropByAtom(AtomOfTerm((Term) _DR), CurrentModule);
ppe = RepPredProp(pe);
return (ppe);
}
if (isappl(_DR)) {
/* char *name = (NameOfFunctor((Functor) *NewC))->StrOfAE; */
int i, arity;
Functor f = FunctorOfTerm((Term) _DR);
if (IsBlobFunctor(f)) {
Yap_Error(TYPE_ERROR_CALLABLE,(Term) _DR,"call/1");
return(FALSE);
}
pe = PredPropByFunc(f, CurrentModule);
ppe = RepPredProp(pe);
_DR=(Cell *) repappl(_DR);
arity = ArityOfFunctor(f);
for(i=1;i<=arity ;i++) {
_DR++;
beam_X[i]=(Cell) _DR;
}
return (ppe);
}
return (NULL);
}
#if DIRECT_JUMP
#define execute_next() goto **((void **) beam_pc)
Cell *TABLE_OPS=NULL;
#else
#define execute_next() goto *OpAddress[*beam_pc]
#endif
int eam_am(PredEntry *initPred);
int eam_am(PredEntry *initPred)
{
static void *OpAddress[]= {
&&exit_eam,
&&top_tree,
&&scheduler,
&&prepare_tries,
&&prepare_calls,
&&get_var_X,
&&get_var_Y,
&&get_val_X,
&&get_val_Y,
&&get_atom,
&&get_list,
&&get_struct,
&&unify_void,
&&unify_val_X,
&&unify_val_Y,
&&unify_var_X,
&&unify_var_Y,
&&unify_atom,
&&unify_list,
&&unify_last_list,
&&unify_struct,
&&unify_last_struct,
&&unify_last_atom,
&&unify_local_X,
&&unify_local_Y,
&&put_var_X,
&&put_var_Y,
&&put_val_X,
&&put_val_Y,
&&put_atom,
&&put_list,
&&put_struct,
&&put_unsafe,
&&put_var_P,
&&write_void,
&&write_var_X,
&&write_var_Y,
&&write_val_X,
&&write_val_Y,
&&write_atom,
&&write_list,
&&write_struct,
&&write_last_list,
&&write_last_struct,
&&write_local_X,
&&write_local_Y,
&&write_var_P,
&&pop,
&&jump,
&&proceed,
&&call,
&&safe_call,
&&safe_call_unary,
&&safe_call_binary,
&&only_1_clause,
&&try_me,
&&retry_me,
&&trust_me,
&&do_nothing,
&&direct_safe_call,
&&direct_safe_call_unary,
&&direct_safe_call_binary,
&&skip_while_var,
&&wait_while_var,
&&force_wait,
&&write_call,
&&is_call,
&&equal_call,
&&cut,
&&commit,
&&fail,
&&save_b_X,
&&save_b_Y,
&&comit_b_X,
&&comit_b_Y,
&&save_appl_X,
&&save_appl_Y,
&&save_pair_X,
&&save_pair_Y,
&&either,
&&orelse,
&&orlast,
&&p_atom,
&&p_atomic,
&&p_equal,
&&p_integer,
&&p_nonvar,
&&p_number,
&&p_var,
&&p_db_ref,
&&p_primitive,
&&p_cut_by,
&&p_save_by,
&&p_succ,
&&p_predc,
&&p_plus,
&&p_minus,
&&p_times,
&&p_div,
&&p_dif,
&&p_eq,
&&p_arg,
&&p_functor
};
#if Debug
static int contador=1;
#endif
Cell code2start[]={_prepare_calls,1,0,_call_op,0,0};
if ((long) initPred==2) { /* retry from call eam(goal) */
goto fail;
} else if ((long) initPred==1) { /* first time call eam(goal) */
initPred=prepare_args_torun();
}
#if DIRECT_JUMP
else if ((long) initPred==0) { /* first time call eam_am. Init TABLE_OPS */
TABLE_OPS=(Cell *) OpAddress;
return(FALSE);
}
#endif
if (initPred==NULL || initPred->beamTable==NULL) return (FALSE);
#if DIRECT_JUMP
code2start[0]=(Cell) OpAddress[_prepare_calls];
code2start[3]=(Cell) OpAddress[_call_op];
#endif
code2start[2]=(Cell) &code2start[5];
code2start[4]=(Cell) initPred;
printf("[ EAM execution started to solve %s/%d ]\n",
initPred->beamTable->name, initPred->beamTable->arity );
initialize_memory_areas();
beam_su=NULL;
beam_OBX=NULL;
beam_ABX=(struct AND_BOX *) request_memory(ANDBOX_SIZE);
beam_ABX->parent=NULL;
beam_ABX->nr_alternative=NULL;
beam_ABX->nr_all_calls=0;
beam_ABX->perms=NULL;
beam_ABX->calls=NULL;
beam_ABX->level=1;
beam_ABX->externals=NULL;
beam_ABX->suspended=NULL;
beam_ABX->side_effects=0;
beam_top=beam_ABX;
if (1) { int i; /* criar mais um nivel acima do top para o caso de haver variaveis na chamada */
beam_ABX->nr_all_calls=1;
beam_ABX->calls= (struct status_and *) request_memory(STATUS_AND_SIZE);
beam_ABX->calls->locals=NULL;
beam_ABX->calls->code=NULL;
beam_ABX->calls->state=RUNNING;
beam_ABX->calls->previous=NULL;
beam_ABX->calls->next=NULL;
beam_OBX= (struct OR_BOX *) request_memory(ORBOX_SIZE);
beam_ABX->calls->call=beam_OBX;
beam_OBX->nr_call=beam_ABX->calls;
beam_OBX->parent=beam_ABX;
beam_OBX->nr_all_alternatives=1;
beam_OBX->eager_split=0;
beam_OBX->alternatives=(struct status_or *) request_memory(STATUS_OR_SIZE);
beam_OBX->alternatives->previous=NULL;
beam_OBX->alternatives->next=NULL;
beam_OBX->alternatives->args=NULL;
beam_OBX->alternatives->code=NULL;
beam_OBX->alternatives->state=RUNNING;
beam_ABX=(struct AND_BOX *) request_memory(ANDBOX_SIZE);
beam_OBX->alternatives->alternative=beam_ABX;
beam_ABX->parent=beam_OBX;
beam_ABX->nr_alternative=beam_OBX->alternatives;
beam_ABX->nr_all_calls=0;
beam_ABX->perms=NULL;
beam_ABX->calls=NULL;
beam_ABX->level=2;
beam_ABX->externals=NULL;
beam_ABX->suspended=NULL;
beam_ABX->side_effects=WRITE;
for(i=1;i<=initPred->beamTable->arity;i++)
add_vars_to_listperms(beam_ABX,(Cell *) beam_X[i]);
}
beam_pc=code2start;
execute_next();
while (1) {
exit_eam:
#if Debug
printf("%5d->(%3d) exit_eam ->",contador++, (int) *beam_pc);
break_debug(contador);
#endif
wake:
#if Debug
printf("%5d->Trying WAKE and_box on suspension \n",contador++);
break_debug(contador);
#endif
if (verify_externals(beam_ABX)==0) goto fail_verify_externals;
if (beam_ABX->externals==NULL) {
beam_nr_call=beam_ABX->calls;
if (beam_nr_alternative->state & END) {
goto success;
}
beam_nr_alternative->state=RUNAGAIN;
goto next_call;
}
beam_nr_alternative->state=SUSPEND;
/* must clear all external assignments */
limpa_trail(beam_ABX);
/* goto top_tree; */
top_tree:
#if Debug
printf("%5d->I'm on top of the Tree (maybe exit or look for suspended alternatives) \n",contador++);
break_debug(contador);
break_top();
#endif
#if GARBAGE_COLLECTOR
if (HEAP_MEM_FULL()) garbage_collector();
#endif
#if USE_LEFTMOST
if (beam_su!=NULL) {
beam_ABX=beam_su->and_box;
beam_OBX=beam_ABX->parent;
beam_nr_alternative=beam_ABX->nr_alternative;
if (beam_nr_alternative->state & (WAKE)) goto wake;
}
beam_ABX=choose_leftmost();
if (beam_ABX==NULL) { /* Must return to next_alternative in beam_OBX BECAUSE EAGER_SPLIT*/
beam_nr_alternative=beam_ABX->nr_alternative;
beam_ABX=beam_OBX->parent;
goto next_alternative;
}
if (beam_ABX!=beam_top && beam_ABX->suspended!=NULL) {
#else
if (beam_su!=NULL) { /* There are suspended alternatives */
beam_ABX=beam_su->and_box;
#endif
#if !Fast_go
if (beam_ABX==NULL || beam_ABX->parent==NULL || beam_ABX->parent->alternatives==NULL) abort_eam("Alternativa NULL NO TOP ?????");
#endif
beam_OBX=beam_ABX->parent;
beam_nr_alternative=beam_ABX->nr_alternative;
if (beam_ABX->suspended->reason==VAR_SUSPENSION) {
delfrom_suspensions_list(beam_ABX->suspended);
beam_nr_call=beam_ABX->calls;
goto next_call;
}
if (beam_ABX->suspended->reason!=NORMAL_SUSPENSION) {
if (beam_ABX->calls->state==WAITING_TO_BE_FIRST ||
(beam_ABX->calls->state & WAITING && is_leftmost(beam_ABX,0))) {
delfrom_suspensions_list(beam_ABX->suspended);
beam_ABX->calls->state=READY;
beam_nr_call=beam_ABX->calls;
goto next_call;
}
#if !USE_LEFTMOST
beam_su=beam_su->next;
goto top_tree;
#endif
}
if (beam_OBX->nr_all_alternatives==1 && beam_ABX->level>beam_OBX->parent->level) {
#if !Fast_go
if (beam_OBX->parent->parent==NULL) abort_eam("Null no top_tree ");
#endif
goto unique_alternative;
}
if (beam_nr_alternative->state & (WAKE)) goto wake;
if (beam_OBX->nr_all_alternatives>1) {
#if Debug
printf("%5d->Trying Fork in suspended and_box \n",contador++);
break_debug(contador);
#endif
/* pickup the left most alternative instead */
split:
beam_OBX=beam_ABX->parent;
#if USE_SPLIT
do_forking_andbox(beam_ABX);
#else
abort_eam("ERROR: Split disable, cannot run non-deterministic programs...");
#endif
beam_OBX=beam_ABX->parent;
beam_nr_alternative=beam_ABX->nr_alternative;
goto unique_alternative;
}
abort_eam("ERROR: exit on top, suspensions still available");
}
/* There is no suspension */
give_solution_toyap();
return (TRUE);
exit_eam("\nExit on top, there is no more work to do... \n");
proceed:
#if Debug
printf("%5d->proceed... \n",contador++);
#endif
if (beam_USE_SAME_ANDBOX!=NULL) { /* was only one alternative */
beam_USE_SAME_ANDBOX=NULL;
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
goto next_call;
}
if (beam_ABX->externals!=NULL) {
beam_nr_alternative->state=SUSPEND_END;
goto suspend;
}
success:
#if Debug
printf("%5d->SUCCESS for call %p in level %d \n",contador++, beam_nr_call, beam_ABX->level );
break_debug(contador);
#endif
/* FOUND SOLUTION -> ALL_SOLUTIONS */
//if ((beam_ABX->side_effects & WRITE) && beam_OBX->nr_all_alternatives>1)
if (beam_OBX->parent==beam_top) {
give_solution_toyap();
return (TRUE);
goto fail;
}
beam_ABX=beam_OBX->parent;
beam_nr_call=beam_OBX->nr_call;
del_orbox_and_sons(beam_OBX);
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
if (beam_ABX->externals!=NULL) {
if (beam_ABX->nr_all_calls==0) {
beam_nr_alternative->state=SUSPEND_END;
} else beam_nr_alternative->state=SUSPEND;
goto suspend;
}
if (beam_ABX->nr_all_calls==0) {
beam_OBX=beam_ABX->parent;
if (beam_OBX==NULL) {
goto top_tree;
}
beam_nr_alternative=beam_ABX->nr_alternative;
goto success;
}
next_call:
#if Debug
printf("%5d->Searching for a next call in and_box... \n",contador++);
break_debug(contador);
#endif
#if GARBAGE_COLLECTOR
if (HEAP_MEM_FULL()) {
garbage_collector();
}
#endif
{ register int nr;
nr=beam_ABX->nr_all_calls;
if (beam_ABX->externals!=NULL && beam_ABX->side_effects<CUT) {
if (nr==0) beam_nr_alternative->state=SUSPEND_END;
else { /* if next call is a cut then execute it */
beam_pc=beam_ABX->calls->code;
#if Debug
if (*beam_pc==_cut_op) {
#else
if (*beam_pc==(Cell) &&cut) {
#endif
beam_nr_call=beam_ABX->calls;
execute_next();
}
beam_nr_alternative->state=SUSPEND;
}
goto suspend;
}
if (nr==0) {
goto success;
}
#if !START_ON_NEXT
beam_nr_call=beam_ABX->calls;
#else
/* if (beam_ABX->parent==beam_OBX) beam_nr_call=beam_ABX->calls; else beam_nr_call=beam_OBX->nr_call->next; */
#endif
while(beam_nr_call!=NULL) {
if (beam_nr_call->state & WAITING) {
if (beam_nr_call->state==WAITING_TO_BE_LEFTMOST) {
if (!is_leftmost(beam_ABX,beam_nr_call)) {
beam_ABX->suspended=addto_suspensions_list(beam_ABX,LEFTMOST_SUSPENSION);
beam_nr_call=NULL;
break;
}
beam_nr_call->state=READY;
}
if (beam_nr_call->state==WAITING_TO_BE_LEFTMOST_PARENT) {
if (!is_leftmost(beam_ABX->parent->parent,beam_ABX->parent->nr_call)) {
beam_ABX->suspended=addto_suspensions_list(beam_ABX,LEFTMOST_SUSPENSION);
beam_nr_call=NULL;
break;
}
beam_nr_call->state=READY;
}
if (beam_nr_call->state==WAITING_TO_BE_FIRST) {
if (beam_nr_call->previous==NULL) {
#if Debug
printf("I can stop Waiting on call %p\n", beam_nr_call);
#endif
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
continue;
}
#if Debug
printf("Force Waiting on call %p\n", beam_nr_call);
#endif
beam_nr_call=NULL;
break;
}
}
if (beam_nr_call->state==READY) {
beam_varlocals=beam_nr_call->locals;
beam_pc=beam_nr_call->code;
execute_next();
}
beam_nr_call=beam_nr_call->next;
}
beam_OBX=beam_ABX->parent;
/* In case (beam_nr_call==nr) */
beam_nr_alternative=beam_ABX->nr_alternative;
if (beam_ABX->externals!=NULL) goto suspend;
if (beam_nr_alternative!=NULL) beam_nr_alternative=beam_nr_alternative->next;
goto next_alternative;
}
fail_body:
fail_head:
fail:
#if Debug
printf("%5d->fail... \n",contador++);
break_debug(contador);
#endif
fail_verify_externals:
if (beam_ABX->externals!=NULL) {
limpa_trail(beam_ABX);
}
beam_OBX=beam_ABX->parent;
beam_nr_alternative=beam_ABX->nr_alternative;
if (beam_OBX==NULL) {
if (beam_ABX==beam_top) return(FALSE);
abort_eam("ERROR -> beam_ABX->parent = NULL (em fail_verify_externals) ?????\n");
}
beam_OBX->nr_all_alternatives=beam_OBX->nr_all_alternatives-1;
if (beam_nr_alternative->next!=NULL) beam_nr_alternative->next->previous=beam_nr_alternative->previous;
if (beam_nr_alternative->previous!=NULL) beam_nr_alternative->previous->next=beam_nr_alternative->next;
else beam_OBX->alternatives=beam_nr_alternative->next; /* apaguei o primeiro da lista */
{ register struct status_or *i;
i=beam_nr_alternative;
beam_nr_alternative=beam_nr_alternative->next;
free_memory((Cell *) i,STATUS_OR_SIZE);
del_andbox_and_sons(beam_ABX);
} /* verificar se existe ainda alguma alternativa viavel nesta or_box */
next_alternative:
#if Debug
printf("%5d->Searching for a next alternative in or_box... \n",contador++);
break_debug(contador);
#endif
#if GARBAGE_COLLECTOR
if (HEAP_MEM_FULL()) garbage_collector();
#endif
if (beam_OBX==NULL) {
#if !Fast_go
if (beam_ABX!=beam_top) abort_eam("Erro no next_Alternative");
#endif
goto top_tree;
}
if (beam_OBX->nr_all_alternatives==0) {
beam_ABX=beam_OBX->parent;
goto fail;
}
if (beam_OBX->nr_all_alternatives==1 && beam_ABX->level>beam_OBX->parent->level) {
beam_nr_alternative=beam_OBX->alternatives;
beam_ABX=beam_OBX->alternatives->alternative;
if (beam_ABX==NULL) {
beam_pc=beam_OBX->alternatives->code;
execute_next();
}
if (beam_OBX->parent->parent==NULL) goto top_tree;
goto unique_alternative;
}
#if !START_ON_NEXT
beam_nr_alternative=beam_OBX->alternatives;
#else
/* if (beam_OBX->parent==beam_ABX) beam_nr_alternative=beam_OBX->alternatives;
else { if (beam_nr_alternative!=NULL) beam_nr_alternative=beam_nr_alternative->next; } */
#endif
while(beam_nr_alternative!=NULL) {
if (beam_nr_alternative->state & (WAKE) ) {
beam_ABX=beam_nr_alternative->alternative;
goto wake;
}
if (beam_nr_alternative->state==READY) {
beam_pc=beam_nr_alternative->code;
execute_next();
}
beam_nr_alternative=beam_nr_alternative->next;
}
/* beam_nr_alternative==NULL -> No more alternatives */
beam_ABX=beam_OBX->parent;
beam_nr_call=beam_OBX->nr_call->next;
goto next_call;
unique_alternative:
#if Debug
printf("%5d->Unique alternative, Does Promotion on and-box\n",contador++);
break_debug(contador);
#endif
#if GARBAGE_COLLECTOR
if (HEAP_MEM_FULL() ) garbage_collector();
#endif
if (beam_OBX->parent->parent==NULL) {
goto top_tree;
}
{ int nr_a;
struct AND_BOX *a;
if (beam_ABX->side_effects >= CUT) {
/* Cut -> Avoid doing the Promotion */
inc_level(beam_ABX,beam_OBX->parent->level-beam_ABX->level);
delfrom_suspensions_list(beam_ABX->suspended);
if (verify_externals(beam_ABX)==0) goto fail_verify_externals;
beam_nr_alternative=beam_ABX->nr_alternative;
if (beam_ABX->externals==NULL) {
beam_nr_call=beam_ABX->calls;
goto next_call;
}
beam_ABX->suspended=addto_suspensions_list(beam_ABX,NORMAL_SUSPENSION);
beam_nr_alternative->state=SUSPEND;
beam_nr_alternative=beam_nr_alternative->next;
goto next_alternative;
}
a=beam_ABX;
beam_ABX=beam_OBX->parent;
nr_a=a->nr_all_calls;
beam_nr_call=beam_OBX->nr_call;
beam_ABX->side_effects+=a->side_effects;
if (nr_a==0) { /* Means SUSPENDED ON END */
beam_nr_call->call=NULL;
beam_nr_call->state=SUCCESS;
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
} else { /* IF nr_all_calls==1 can be optimized ????? */
if (nr_a==1) {
if (a->calls->call!=NULL) {
a->calls->call->nr_call=beam_nr_call;
a->calls->call->parent=beam_ABX;
}
beam_nr_call->call=a->calls->call;
beam_nr_call->locals=a->calls->locals;
beam_nr_call->code=a->calls->code;
beam_nr_call->state=a->calls->state;
free_memory((Cell *) a->calls,STATUS_AND_SIZE);
} else {
struct status_and *first, *last;
int nr;
nr=beam_ABX->nr_all_calls;
first=a->calls;
last=a->calls;
while(1) {
if (last->call!=NULL) {
last->call->parent=beam_ABX;
}
if (last->next==NULL) break;
last=last->next;
}
last->next=beam_nr_call->next;
if (beam_nr_call->next!=NULL) beam_nr_call->next->previous=last;
first->previous=beam_nr_call->previous;
if (beam_nr_call->previous!=NULL) beam_nr_call->previous->next=first;
else beam_ABX->calls=first; /* nr_call era o primeiro */
free_memory((Cell *) beam_nr_call,STATUS_AND_SIZE);
beam_nr_call=first;
beam_ABX->nr_all_calls=nr+nr_a-1;
}
/* Set local vars from a to point to new and_box beam_ABX */
}
move_perm_vars(a,beam_ABX);
/* change local vars suspensions to point to new andbox */
{ struct EXTERNAL_VAR *end,*e;
e=a->externals;
end=NULL;
while(e!=NULL) {
struct SUSPENSIONS_VAR *s;
s=e->var->suspensions;
while(s!=NULL) {
if (s->and_box==a) { s->and_box=beam_ABX; break; }
s=s->next;
}
end=e;
e=e->next;
}
/* Clear bindings made on externals so that we are able to
run the verify externals */
e=beam_ABX->externals;
while(e!=NULL) {
struct PERM_VAR *v;
v=e->var;
*((Cell *) v)=(Cell) v;
e=e->next;
}
if (end!=NULL) {
end->next=beam_ABX->externals;
beam_ABX->externals=a->externals;
}
delfrom_suspensions_list(a->suspended); /* remove suspensions */
free_memory((Cell *) a,ANDBOX_SIZE);
free_memory((Cell *) beam_OBX->alternatives,STATUS_OR_SIZE);
free_memory((Cell *) beam_OBX,ORBOX_SIZE);
beam_OBX=beam_ABX->parent;
if (verify_externals(beam_ABX)==0) goto fail_verify_externals;
}
beam_nr_alternative=beam_ABX->nr_alternative;
if (beam_ABX->externals==NULL) {
beam_nr_call=beam_ABX->calls;
goto next_call;
}
beam_ABX->suspended=addto_suspensions_list(beam_ABX,NORMAL_SUSPENSION);
beam_nr_alternative->state=SUSPEND;
beam_nr_alternative=beam_nr_alternative->next;
goto next_alternative;
}
abort_eam("cheguei aqui para tentar executar o prepare_tries antigo...\n");
prepare_tries:
#if Debug
printf("%5d->prepare_tries for %d clauses with arity=%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
if (!arg1) goto fail;
{ register int nr;
nr=arg1;
if (nr==1 && beam_ABX->parent!=NULL) {
beam_ES=0;
beam_nr_call->state=RUNNING;
beam_pc+=3;
/* execute_next(); */
goto only_1_clause;
}
beam_OBX=(struct OR_BOX *) request_memory(ORBOX_SIZE);
beam_nr_call->call=beam_OBX;
beam_nr_call->state=RUNNING;
beam_OBX->nr_call=beam_nr_call;
beam_OBX->parent=beam_ABX;
beam_OBX->eager_split=beam_ES;
beam_ES=0;
beam_OBX->nr_all_alternatives=nr;
{ register int i;
register struct status_or *p=NULL;
register Cell *a;
if (nr>1) a=save_arguments(arg2); else a=NULL;
beam_pc+=3;
for(i=0;i<nr;i++) {
beam_nr_alternative=(struct status_or *) request_memory(STATUS_OR_SIZE);
if (i==0) beam_OBX->alternatives=beam_nr_alternative; else p->next=beam_nr_alternative;
beam_nr_alternative->previous=p;
p=beam_nr_alternative;
beam_nr_alternative->alternative=NULL;
beam_nr_alternative->code=beam_pc;
beam_nr_alternative->state=READY;
beam_nr_alternative->args=a;
beam_pc+=5;
}
beam_nr_alternative->next=NULL;
}
}
beam_nr_alternative=beam_OBX->alternatives;
/* goto next_alternative; */
beam_pc=beam_nr_alternative->code;
goto try_me;
execute_next();
/* explore_alternative */
trust_me:
get_arguments(arg2,beam_nr_alternative->args);
remove_memory_arguments(beam_nr_alternative->args);
goto try_me;
retry_me:
get_arguments(arg2,beam_nr_alternative->args);
try_me:
beam_nr_alternative->args=NULL;
#if Debug
printf("%5d->Create AND_BOX for the %dth clause of predicate %s/%d (Yvars=%d) \n",contador++,(int) arg4,((struct Clauses *)arg1)->predi->name,(int) arg2,(int) arg3);
break_debug(contador);
#endif
if (beam_OBX->nr_all_alternatives>1 || beam_OBX->parent->parent==NULL) {
beam_USE_SAME_ANDBOX=NULL;
beam_ABX=(struct AND_BOX *)request_memory(ANDBOX_SIZE);
beam_nr_alternative->alternative=beam_ABX;
beam_nr_alternative->state=RUNNING;
beam_ABX->nr_alternative=beam_nr_alternative;
beam_ABX->level=beam_OBX->parent->level+1;
beam_ABX->parent=beam_OBX;
beam_ABX->externals=NULL;
beam_ABX->suspended=NULL;
beam_ABX->perms=NULL;
beam_ABX->calls=NULL;
beam_ABX->nr_all_calls=0;
beam_ABX->side_effects=((struct Clauses *)arg1)->side_effects;
/* continue on middle of only_1_clause code */
} else {
beam_nr_call=beam_OBX->nr_call;
beam_ABX=beam_OBX->parent;
del_orbox_and_sons(beam_OBX);
beam_nr_call->call=NULL;
/* continue to only 1 clause */
only_1_clause:
#if Debug
printf("Only 1 Clause -> Use the same AND_BOX for the %dth clause of predicate %s/%d (Yvars=%d) \n",(int) arg4,((struct Clauses *)arg1)->predi->name,(int) arg2,(int) arg3);
#endif
if (((struct Clauses *)arg1)->side_effects >= CUT) {
/* printf("Must create or-box still the same ?????\n"); MUST SEE THIS CASE */
}
beam_USE_SAME_ANDBOX=beam_nr_call;
beam_nr_alternative=beam_ABX->nr_alternative;
beam_OBX=beam_ABX->parent;
}
if (arg3) {
register int nr_locals;
nr_locals=arg3;
/* nr_locals=((struct Clauses *)arg1)->nr_vars; */
beam_varlocals=request_memory_locals(nr_locals);
// add_to_list_locals(beam_varlocals,beam_ABX);
} else {
beam_varlocals=NULL;
}
beam_pc=((struct Clauses *)arg1)->code+5;
execute_next();
prepare_calls:
#if Debug
printf("%5d->prepare_calls %d\n",contador++,(int) arg1);
break_debug(contador);
#endif
if (beam_USE_SAME_ANDBOX!=NULL) { /* only one alternative */
register int nr;
nr=(int) arg1;
beam_pc+=2;
if (nr) {
beam_nr_call=beam_USE_SAME_ANDBOX;
if (nr==1) { /* ONLY ONE CALL , CHANGE DIRECTLY */
beam_nr_call->call=NULL;
beam_nr_call->code=beam_pc+1;
beam_nr_call->locals=beam_varlocals;
beam_nr_call->state=READY;
} else {
struct status_and *calls,*first=NULL,*last=NULL;
int i,nr2;
nr2=beam_ABX->nr_all_calls;
for(i=0;i<nr;i++) {
calls=(struct status_and *) request_memory(STATUS_AND_SIZE);
if (first==NULL) first=calls;
if (last!=NULL) last->next=calls;
calls->previous=last;
calls->call=NULL;
calls->code=beam_pc+1;
calls->locals=beam_varlocals;
calls->state=READY;
beam_pc=(Cell *) *beam_pc;
last=calls;
}
last->next=beam_nr_call->next;
if (beam_nr_call->next!=NULL) beam_nr_call->next->previous=last;
first->previous=beam_nr_call->previous;
if (beam_nr_call->previous!=NULL) beam_nr_call->previous->next=first;
else beam_ABX->calls=first; /* nr_call era o primeiro */
free_memory((Cell *) beam_nr_call,STATUS_AND_SIZE);
beam_nr_call=first;
beam_ABX->nr_all_calls=nr+nr2-1;
}
} else {
beam_nr_call->call=NULL;
}
} else
{ /* there where more than one alternative */
register int nr;
nr=(int) arg1;
beam_pc+=2;
beam_ABX->nr_all_calls=nr;
if (nr) {
struct status_and *calls, *first=NULL, *last=NULL;
register int i;
for(i=0;i<nr;i++) {
calls=(struct status_and *) request_memory(STATUS_AND_SIZE);
if (first==NULL) first=calls;
if (last!=NULL) last->next=calls;
calls->previous=last;
calls->call=NULL;
calls->code=beam_pc+1;
calls->locals=beam_varlocals;
calls->state=READY;
beam_pc=(Cell *) *beam_pc;
last=calls;
}
last->next=NULL;
beam_ABX->calls=first;
} else beam_ABX->calls=NULL;
beam_nr_call=beam_ABX->calls;
}
/* goto scheduler;*/
scheduler:
#if Debug
printf("%5d->Scheduler... \n",contador++);
break_debug(contador);
#endif
#if Debug_Dump_State
dump_eam_state();
#endif
/* Have to decide if I go up or continue on same level */
/* If I go up the I have to suspend the and_box,
else I can continue to the next clause (1st) of the and_box
Another Alternative is to pick up a SUSPEND and_box */
/* for the meantime I Will always suspend unless there is a cut */
if (beam_ABX->externals==NULL || beam_ABX->side_effects>=CUT) {
beam_pc=beam_nr_call->code;
execute_next();
}
beam_nr_alternative->state=SUSPEND;
/* goto suspend; */
suspend:
#if Debug
printf("%5d->SUSPEND on alternative %p\n",contador++,beam_nr_alternative);
break_debug(contador);
#endif
beam_OBX=beam_ABX->parent;
{ struct EXTERNAL_VAR *e;
struct PERM_VAR *v;
struct SUSPENSIONS_VAR *s;
beam_ABX->suspended=addto_suspensions_list(beam_ABX,NORMAL_SUSPENSION);
e=beam_ABX->externals;
while(e!=NULL) {
v=e->var;
*((Cell *) v)=(Cell) v;
if (v->suspensions==NULL || v->suspensions->and_box!=beam_ABX) {
/* se a and_box ja esta na lista nao adiciona */
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE);
s->and_box=beam_ABX;
s->next=v->suspensions;
v->suspensions=s;
}
e=e->next;
}
}
if (beam_OBX->eager_split) goto split;
beam_nr_alternative=beam_nr_alternative->next;
goto next_alternative;
call_yap:
/* Must create term to call */
/* YAP_RunGoal(t_goal); */
if (!Yap_execute_goal(beam_X[1],0,CurrentModule)) goto success;
else goto fail;
call:
#if Debug
printf("%5d->call %s/%d \n",contador++,((PredEntry *) arg1)->beamTable->name,(int) ((PredEntry *) arg1)->beamTable->arity);
break_debug(contador);
#endif
beam_ES=((PredEntry *) arg1)->beamTable->eager_split;
/* CUIDADO : vou tentar libertar a memoria caso seja o ultimo call */
#if DIRECT_JUMP
if ((void *) arg3==&&exit_eam) /* Estou no ultimo call deste predicado */
#else
if (arg3==_exit_eam) /* Estou no ultimo call deste predicado */
#endif
{
if (beam_ABX->nr_all_calls==1) {
free_memory_locals(beam_nr_call->locals);
} else {
struct status_and *calls;
calls=beam_ABX->calls;
while(calls!=beam_nr_call) {
if (calls->locals==beam_nr_call->locals) break;
calls=calls->next;
}
if (calls==beam_nr_call) {
free_memory_locals(beam_nr_call->locals);
}
}
}
beam_nr_call->locals=NULL;
bpEntry=(PredEntry *) arg1;
beam_ALTERNATIVES=beam_H;
Yap_absmi(-9000);
{
int NR_INDEXED;
NR_INDEXED=beam_ALTERNATIVES-beam_H;
#if Debug
printf("Back from yap-index with %d alternativas\n",NR_INDEXED);
#endif
if (NR_INDEXED==0) goto fail;
if (NR_INDEXED==1 && beam_ABX->parent!=NULL) {
struct Clauses *clause=(struct Clauses *) *(beam_H);
beam_ES=0;
beam_nr_call->state=RUNNING;
#if Debug
printf("Only 1 Alternative\n");
#endif
if (clause->side_effects >= CUT) {
/* printf("Must create or-box still the same ?????\n"); RSLOPES: MUST SEE THIS CASE */
}
beam_USE_SAME_ANDBOX=beam_nr_call;
beam_nr_alternative=beam_ABX->nr_alternative;
beam_OBX=beam_ABX->parent;
if (clause->nr_vars) {
register int nr_locals;
nr_locals=clause->nr_vars;
beam_varlocals=request_memory_locals(nr_locals);
// add_to_list_locals(beam_varlocals,beam_ABX);
} else {
beam_varlocals=NULL;
}
beam_pc=clause->code+5;
execute_next();
} else {
int i, arity;
struct status_or *p=NULL;
Cell *a;
arity=((PredEntry *) arg1)->beamTable->arity;
beam_OBX=(struct OR_BOX *) request_memory(ORBOX_SIZE);
beam_nr_call->call=beam_OBX;
beam_nr_call->state=RUNNING;
beam_OBX->nr_call=beam_nr_call;
beam_OBX->parent=beam_ABX;
beam_OBX->eager_split=beam_ES;
beam_ES=0;
beam_OBX->nr_all_alternatives=NR_INDEXED;
if (NR_INDEXED>1) a=save_arguments(arity); else a=NULL;
for(i=0;i<NR_INDEXED;i++) {
beam_nr_alternative=(struct status_or *) request_memory(STATUS_OR_SIZE);
if (i==0) beam_OBX->alternatives=beam_nr_alternative; else p->next=beam_nr_alternative;
beam_nr_alternative->previous=p;
p=beam_nr_alternative;
beam_nr_alternative->alternative=NULL;
beam_pc=((struct Clauses *) beam_H[i])->code;
#if DIRECT_JUMP
if (i==0) {
if (NR_INDEXED==1) *beam_pc=(Cell) &&only_1_clause;
else *beam_pc=(Cell) &&try_me;
} else if (i==NR_INDEXED-1) *beam_pc=(Cell) &&trust_me;
else *beam_pc=(Cell) &&retry_me;
#else
if (i==0) {
if (NR_INDEXED==1) *beam_pc=_only_1_clause_op;
else *beam_pc=_try_me_op;
} else if (i==NR_INDEXED-1) *beam_pc=_trust_me_op;
else *beam_pc=_retry_me_op;
#endif
arg2=arity;
arg1=beam_H[i];
arg3=((struct Clauses *) beam_H[i])->nr_vars;
arg4=i;
beam_nr_alternative->code=beam_pc;
beam_nr_alternative->state=READY;
beam_nr_alternative->args=a;
}
beam_nr_alternative->next=NULL;
beam_nr_alternative=beam_OBX->alternatives;
/* goto next_alternative; */
beam_pc=beam_nr_alternative->code;
execute_next();
}
}
/* goto prepare_tries; */
safe_call:
#if Debug
printf("%5d->safe_call 0x%lX X1=%d (0x%lX) ,X2=%d (0x%lX) \n",contador++,(unsigned long) arg1,(int) beam_X[1],(unsigned long) beam_X[1],(int) beam_X[2],(unsigned long) beam_X[2]);
break_debug(contador);
#endif
beam_S=(Cell *) arg1;
beam_S=(Cell *) (* ((int long (*)(void)) beam_S))();
if (!beam_S) goto fail_body;
/* we didn't get to created a or_box */
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
beam_OBX=beam_ABX->parent;
goto next_call;
safe_call_unary:
#if Debug
printf("%5d->safe_call_unary 0x%lX X1=%d (0x%lX) ,X2=%d (0x%lX) \n",contador++,(unsigned long) arg1,(int) beam_X[1],(unsigned long) beam_X[1],(int) beam_X[2],(unsigned long) beam_X[2]);
break_debug(contador);
#endif
beam_S=(Cell *) arg1;
beam_S=(Cell *) (* ((int long (*)(Term)) beam_S))(deref(beam_X[1]));
if (!beam_S) goto fail_body;
/* we didn't get to created a or_box */
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
beam_OBX=beam_ABX->parent;
goto next_call;
safe_call_binary:
#if Debug
printf("%5d->safe_call_binary 0x%lX X1=%d (0x%lX) ,X2=%d (0x%lX) \n",contador++,(unsigned long) arg1,(int) beam_X[1],(unsigned long) beam_X[1],(int) beam_X[2],(unsigned long) beam_X[2]);
break_debug(contador);
#endif
beam_S=(Cell *) arg1;
beam_S=(Cell *) (* ((int long (*)(Term, Term)) beam_S))(deref(beam_X[1]),deref(beam_X[2]));
if (!beam_S) goto fail_body;
/* we didn't get to created a or_box */
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
beam_OBX=beam_ABX->parent;
goto next_call;
direct_safe_call:
#if Debug
printf("%5d->direct_safe_call %p X1=%d,X2=%d \n",contador++,(void *) arg1,(int) beam_X[1],(int) beam_X[2]);
break_debug(contador);
#endif
beam_S=(Cell *) arg1;
beam_S=(Cell *) (* ((int long (*)(void)) beam_S))();
/* beam_S=(Cell *) (* ((int long (*)(Term,Term)) beam_S))(beam_X[1],beam_X[2]); */
if (!beam_S) goto fail_head;
beam_pc+=2;
execute_next();
direct_safe_call_unary:
#if Debug
printf("%5d->direct_safe_call_unary %p X1=%d,X2=%d \n",contador++,(void *) arg1,(int) beam_X[1],(int) beam_X[2]);
break_debug(contador);
#endif
beam_S=(Cell *) arg1;
beam_S=(Cell *) (* ((int long (*)(Term)) beam_S))(deref(beam_X[1]));
if (!beam_S) goto fail_head;
beam_pc+=2;
execute_next();
direct_safe_call_binary:
#if Debug
printf("%5d->direct_safe_call_binary %p X1=%d,X2=%d \n",contador++,(void *) arg1,(int) beam_X[1],(int) beam_X[2]);
break_debug(contador);
#endif
beam_S=(Cell *) arg1;
beam_S=(Cell *) (* ((int long (*)(Term,Term)) beam_S))(deref(beam_X[1]),deref(beam_X[2]));
if (!beam_S) goto fail_head;
beam_pc+=2;
execute_next();
skip_while_var:
#if Debug
printf("%5d->Skip_while_var on call %p\n",contador++, beam_nr_call);
break_debug(contador);
#endif
if (exists_var_in((Cell *) beam_X[1])) {
beam_ABX->suspended=addto_suspensions_list(beam_ABX,VAR_SUSPENSION);
beam_nr_call=beam_nr_call->next;
goto next_call;
}
beam_pc+=1;
execute_next();
wait_while_var:
#if Debug
printf("%5d->Wait_while_var on call %p\n",contador++, beam_nr_call);
break_debug(contador);
#endif
if (exists_var_in((Cell *) beam_X[1])) {
beam_ABX->suspended=addto_suspensions_list(beam_ABX,VAR_SUSPENSION);
beam_OBX=beam_ABX->parent;
beam_nr_alternative=beam_ABX->nr_alternative->next;
goto next_alternative;
}
beam_pc+=1;
execute_next();
force_wait:
#if Debug
printf("%5d->Force Waiting on call %p\n",contador++, beam_nr_call);
break_debug(contador);
#endif
/* we didn't get to created a or_box */
beam_OBX=beam_ABX->parent;
if (beam_nr_call->previous!=NULL) {
beam_nr_call->call=NULL;
beam_nr_call->state=WAITING_TO_BE_FIRST;
beam_ABX->suspended=addto_suspensions_list(beam_ABX,WAIT_SUSPENSION);
beam_nr_alternative=beam_ABX->nr_alternative->next;
goto next_alternative;
}
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
goto next_call;
write_call:
#if Debug
printf("%5d->write_call\n",contador++);
break_debug(contador);
#endif
#if USE_LEFTMOST
if (!is_leftmost(beam_ABX,beam_nr_call)) {
#if Debug
printf("Force Waiting Before write_call\n");
#endif
beam_nr_call->call=NULL;
beam_nr_call->state=WAITING_TO_BE_LEFTMOST;
beam_ABX->suspended=addto_suspensions_list(beam_ABX,LEFTMOST_SUSPENSION);
goto top_tree;
}
#endif
#ifdef DEBUG
Yap_plwrite ((Term) beam_X[1], NULL, 0, GLOBAL_MaxPriority);
#else
extern int beam_write (void);
beam_write();
#endif
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
beam_ABX->side_effects=beam_ABX->side_effects | WRITE;
beam_OBX=beam_ABX->parent;
goto next_call;
is_call:
#if Debug
printf("%5d->is_call\n",contador++);
break_debug(contador);
#endif
{
Cell *_DR;
/* BEAM_is is declared on C/eval.c */
_DR=(Cell *) BEAM_is();
if (_DR==NULL) { /* erro no Eval */
beam_top=NULL;
return (FALSE);
}
if (!Unify((Cell *) beam_X[1],_DR)) goto fail_body;
}
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
beam_OBX=beam_ABX->parent;
goto next_call;
equal_call:
#if Debug
printf("%5d->equal_call\n",contador++);
break_debug(contador);
#endif
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
if (beam_ABX->externals!=NULL) {
if (beam_ABX->nr_all_calls==0) {
beam_nr_alternative->state=SUSPEND_END;
} else beam_nr_alternative->state=SUSPEND;
goto suspend;
}
goto next_call;
pop:
#if Debug
printf("%5d->pop %d \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (arg1>1) {
beam_sp+=arg1>>2;
}
pop_mode_and_sreg();
#if Debug
if (beam_Mode==READ) printf("Continues in READ mode\n");
else printf("Continues in WRITE mode\n");
#endif
beam_pc+=2;
execute_next();
do_nothing:
#if Debug
printf("%5d->do_nothing \n",contador++);
break_debug(contador);
#endif
beam_pc++;
execute_next();
get_var_X:
#if Debug
printf("%5d->get_var_X X%d=X%d \n",contador++,(int) arg2,(int) arg1);
break_debug(contador);
#endif
beam_X[arg2]=beam_X[arg1];
beam_pc+=3;
execute_next();
get_var_Y:
#if Debug
printf("%5d->get_var_Y Y%d=X%d \n",contador++,(int) arg2,(int) arg1);
break_debug(contador);
#endif
beam_varlocals[arg2]=beam_X[arg1];
#if !Fast_go
{ Cell *a;
a = (Cell *) deref(beam_X[arg1]);
if(isvar(a) && !isappl(a) && !is_perm_var(a))
abort_eam("S<EFBFBD>rio problema no get_var_Y\n");
/* acho que vou ter de criar uma variavel local nova no nivel superior */
}
#endif
beam_pc+=3;
execute_next();
get_val_X:
#if Debug
printf("%5d->get_val_X X%d,X%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
{ register Cell *_DR, *_DR1;
_DR=(Cell *) deref(beam_X[arg1]);
if (isvar((Cell) _DR)) {
_DR1=(Cell *) deref(beam_X[arg2]);
if (!isvar((Cell) _DR1)) {
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
UnifyCells(_DR,_DR1);
}
} else {
_DR1=(Cell *) deref(beam_X[arg2]);
if (isvar((Cell) _DR1)) {
*(_DR1)=(Cell) _DR;
trail(beam_ABX,(struct PERM_VAR *) _DR1);
} else {
if (!Unify(_DR1,_DR)) goto fail_head;
}
}
}
beam_pc+=3;
execute_next();
get_val_Y:
#if Debug
printf("%5d->get_val_Y X%d,Y%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
{ register Cell *_DR, *_DR1;
_DR=(Cell *) deref(beam_X[arg1]);
if (isvar((Cell) _DR)) {
_DR1=(Cell *) deref(beam_varlocals[arg2]);
if (!isvar((Cell) _DR1)) {
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
UnifyCells(_DR,_DR1);
}
} else {
_DR1=(Cell *) deref(beam_varlocals[arg2]);
if (isvar((Cell) _DR1)) {
*(_DR1)=(Cell) _DR;
trail(beam_ABX,(struct PERM_VAR *) _DR1);
} else {
if (!Unify(_DR1,_DR)) goto fail_head;
}
}
}
beam_pc+=3;
execute_next();
get_atom:
#if Debug
printf("%5d->get_atom X%d, 0x%lX\n",contador++,(int) arg1,(unsigned long) arg2);
break_debug(contador);
#endif
{ register Cell *_DR;
_DR=(Cell *) deref(beam_X[arg1]);
if (isvar((Cell) _DR)) {
*(_DR)=arg2;
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
if ((Cell) _DR!=arg2) goto fail_head;
}
}
beam_pc+=3;
execute_next();
get_list:
#if Debug
printf("%5d->get_list X%d\n",contador++,(int) arg1);
break_debug(contador);
#endif
{ register Cell *_DR, *_DR1;
_DR=(Cell *) deref(beam_X[arg1]);
if (isvar((Cell) _DR)) { beam_Mode=WRITE;
beam_S = beam_H;
beam_H+= 2;
_DR1=(Cell *) abspair(beam_S);
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
beam_pc+=2;
execute_next();
} else {
if (!ispair((Cell) _DR)) goto fail_head;
beam_Mode=READ;
_DR1=_DR; /* SaveExpression in DR1*/
beam_S=(Cell *) reppair((Cell) _DR);
beam_pc+=2;
execute_next();
}
}
get_struct:
#if Debug
printf("%5d->get_struct X%d, 0x%lX/%d\n",contador++,(int) arg1,(unsigned long) arg2,(int) arg3);
break_debug(contador);
#endif
{ register Cell *_DR, *_DR1;
_DR=(Cell *) deref(beam_X[arg1]);
if (isvar((Cell) _DR)) { beam_Mode=WRITE;
_DR1=(Cell *) absappl((Cell) beam_H); /* SaveExpression in _DR1*/
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
*( beam_H++)=arg2;
beam_S= beam_H;
beam_H+=arg3; /* arg3 = arity */
beam_pc+=4;
execute_next();
} else {
if (!isappl((Cell) _DR)) goto fail_head;
beam_Mode=READ;
beam_S=(Cell *) repappl((Cell) _DR);
if (*beam_S!=arg2) goto fail_head;
beam_S++;
_DR1=_DR; /* SaveExpression in _DR1*/
beam_pc+=4;
execute_next();
}
}
unify_void:
#if Debug
printf("%5d->unify_void\n",contador++);
break_debug(contador);
#endif
if (beam_Mode==WRITE) {
*beam_S=(Cell) request_permVar(beam_ABX);
}
beam_S++;
beam_pc+=1;
execute_next();
unify_local_Y:
#if Debug
printf("%5d->unify_local_Y Y%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR1=(Cell *) deref(beam_varlocals[arg1]);
if (isvar((Cell) _DR1)) {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
UnifyCells(_DR1,_DR); /* var , var */
} else {
*(_DR1)=(Cell) _DR; /* var , nonvar */
trail(beam_ABX,(struct PERM_VAR *) _DR1);
}
}
else {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
*(_DR)=(Cell) _DR1; /* nonvar, var */
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
if (!Unify(_DR,_DR1)) goto fail_head; /* nonvar, nonvar */
}
}
beam_S++;
beam_pc+=2;
execute_next();
} else { /* write Mode */
register Cell *_DR;
_DR=(Cell *) deref(beam_varlocals[arg1]);
if (isvar((Cell) _DR) && !is_perm_var((Cell *) _DR)) {
*beam_S=(Cell) request_permVar(beam_ABX);
UnifyCells(_DR,beam_S);
} else {
*(beam_S)=(Cell) _DR;
}
beam_S++;
beam_pc+=2;
execute_next();
}
unify_local_X:
#if Debug
printf("%5d->unify_local_X X%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR1=(Cell *) deref(beam_X[arg1]);
if (isvar((Cell) _DR1)) {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
UnifyCells(_DR1,_DR); /* var , var */
} else {
*(_DR1)=(Cell) _DR; /* var , nonvar */
trail(beam_ABX,(struct PERM_VAR *) _DR1);
}
}
else {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
*(_DR)=(Cell) _DR1; /* nonvar, var */
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
if (!Unify(_DR,_DR1)) goto fail_head; /* nonvar, nonvar */
}
}
beam_S++;
beam_pc+=2;
execute_next();
} else { /* write mode */
register Cell *_DR;
_DR=(Cell *) deref(beam_X[arg1]);
if (isvar((Cell) _DR) && !is_perm_var((Cell *) _DR)) {
*beam_S=(Cell) request_permVar(beam_ABX);
UnifyCells(_DR,beam_S);
} else {
*(beam_S)=(Cell) _DR;
}
beam_S++;
beam_pc+=2;
execute_next();
}
unify_val_Y:
#if Debug
printf("%5d->unify_val_Y Y%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR1=(Cell *) deref(beam_varlocals[arg1]);
if (isvar((Cell) _DR1)) {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
UnifyCells(_DR1,_DR);
} else {
*(_DR1)=(Cell) _DR;
trail(beam_ABX,(struct PERM_VAR *) _DR1);
}
}
else {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
if (!Unify(_DR,_DR1)) goto fail_head;
}
}
beam_S++;
beam_pc+=2;
execute_next();
} else { /* write mode */
*(beam_S)=beam_varlocals[arg1];
beam_S++;
beam_pc+=2;
execute_next();
}
unify_val_X:
#if Debug
printf("%5d->unify_val_X X%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR1=(Cell *) deref((Cell) beam_X[arg1]);
if (isvar((Cell) _DR1)) {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
UnifyCells(_DR1,_DR);
} else {
*(_DR1)=(Cell) _DR;
trail(beam_ABX,(struct PERM_VAR *) _DR1);
}
}
else {
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
if (!Unify(_DR,_DR1)) goto fail_head;
}
}
beam_S++;
beam_pc+=2;
execute_next();
} else {
*(beam_S)=beam_X[arg1];
beam_S++;
beam_pc+=2;
execute_next();
}
unify_var_X:
#if Debug
printf("%5d->unify_var_X X%d=*S \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (beam_Mode==READ) {
beam_X[arg1]=*(beam_S++);
beam_pc+=2;
execute_next();
} else {
*beam_S=(Cell) request_permVar(beam_ABX);
beam_X[arg1]=(Cell) beam_S;
beam_S++;
beam_pc+=2;
execute_next();
}
unify_var_Y:
#if Debug
printf("%5d->unify_var_Y Y%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (beam_Mode==READ) {
beam_varlocals[arg1]=*(beam_S++);
beam_pc+=2;
execute_next();
} else {
*beam_S=(Cell )request_permVar(beam_ABX);
beam_varlocals[arg1]=*beam_S;
beam_S++;
beam_pc+=2;
execute_next();
}
unify_last_atom:
unify_atom:
#if Debug
printf("%5d->unify_atom 0x%lX \n",contador++,(unsigned long) arg1);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR;
_DR=(Cell *) deref((Cell) beam_S);
if (isvar((Cell) _DR)) {
*(_DR)=arg1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
} else {
if ((Cell) _DR!=arg1) goto fail_head;
}
beam_S++;
beam_pc+=2;
execute_next();
} else {
*(beam_S)=arg1;
beam_S++;
beam_pc+=2;
execute_next();
}
unify_list:
#if Debug
printf("%5d->unify_list \n",contador++);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR=(Cell *) deref(*beam_S);
if (isvar((Cell) _DR)) {
_DR1=(Cell *) abspair((Cell) beam_H); /* SavedExpression in _DR1 */
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
beam_S++;
push_mode_and_sreg();
beam_Mode=WRITE; /* goes int write mode */
beam_S= beam_H;
beam_H+=2;
beam_pc+=1;
execute_next();
} else {
if (!ispair((Cell) _DR)) goto fail_head;
beam_S++;
push_mode_and_sreg();
beam_S=(Cell *) reppair((Cell) _DR);
_DR1=_DR; /* SavedExpression in _DR1 */
beam_pc+=1;
execute_next();
}
} else {
register Cell *_DR1;
_DR1=(Cell *) abspair((Cell) beam_H); /* SavedExpression in _DR1 */
*(beam_S)=(Cell) _DR1;
beam_S++;
push_mode_and_sreg();
beam_S= beam_H;
beam_H+=2;
beam_pc+=1;
execute_next();
}
unify_last_list:
#if Debug
printf("%5d->unify_last_list \n",contador++);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR=(Cell *) deref(*beam_S);
if (isvar((Cell) _DR)) { beam_Mode=WRITE; /* goes into write mode */
_DR1=(Cell *) abspair((Cell) beam_H); /* SavedExpression in _DR1 */
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
beam_S= beam_H;
beam_H+=2;
beam_pc+=1;
execute_next();
} else {
if (!ispair((Cell) _DR)) goto fail_head;
beam_S=(Cell *) reppair((Cell) _DR);
_DR1=_DR; /* SavedExpression in _DR1 */
beam_pc+=1;
execute_next();
}
} else {
register Cell *_DR1;
_DR1=(Cell *) abspair((Cell) beam_H); /* SavedExpression in _DR1 */
*(beam_S)=(Cell) _DR1;
beam_S= beam_H;
beam_H+=2;
beam_pc+=1;
execute_next();
}
unify_struct:
#if Debug
printf("%5d->unify_struct 0x%lX,%d \n",contador++,(unsigned long) arg1,(int) arg2);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR=(Cell *) deref(*beam_S);
if (isvar((Cell) _DR)) {
_DR1=(Cell *) absappl((Cell) beam_H); /* SaveExpression in _DR1*/
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
beam_S++;
push_mode_and_sreg();
beam_Mode=WRITE; /* goes into write mode */
*( beam_H++)=arg1;
beam_S= beam_H;
beam_H+=arg2;
beam_pc+=3;
execute_next();
} else {
if (!isappl((Cell) _DR)) goto fail_head;
_DR1=(Cell *) repappl((Cell) _DR);
if (*_DR1!=arg1) goto fail_head;
++beam_S;
push_mode_and_sreg();
beam_S=++_DR1;
_DR1=_DR; /* SaveExpression in _DR1*/
beam_pc+=3;
execute_next();
}
} else {
register Cell *_DR1;
_DR1=(Cell *) absappl((Cell) beam_H); /* SaveExpression in _DR1*/
*(beam_S)=(Cell) _DR1;
beam_S++;
push_mode_and_sreg();
*( beam_H++)=arg1;
beam_S= beam_H;
beam_H+=arg2;
beam_pc+=3;
execute_next();
}
unify_last_struct:
#if Debug
printf("%5d->unify_last_struct 0x%lX, %d \n",contador++,(unsigned long) arg1,(int) arg2);
break_debug(contador);
#endif
if (beam_Mode==READ) {
register Cell *_DR, *_DR1;
_DR=(Cell *) deref(*beam_S);
if (isvar((Cell) _DR)) { beam_Mode=WRITE; /* goes into write mode */
_DR1=(Cell *) absappl((Cell) beam_H); /* SaveExpression in _DR1*/
*(_DR)=(Cell) _DR1;
trail(beam_ABX,(struct PERM_VAR *) _DR);
*( beam_H++)=arg1;
beam_S= beam_H;
beam_H+=arg2;
beam_pc+=3;
execute_next();
} else {
if (!isappl((Cell) _DR)) goto fail_head;
_DR1=(Cell *) repappl((Cell) _DR);
if (*_DR1!=arg1) goto fail_head;
beam_S=++_DR1;
_DR1=_DR; /* SaveExpression in _DR1*/
beam_pc+=3;
execute_next();
}
} else {
register Cell *_DR1;
_DR1=(Cell *) absappl((Cell) beam_H); /* SaveExpression in _DR1*/
*(beam_S)=(Cell) _DR1;
*( beam_H++)=arg1;
beam_S= beam_H;
beam_H+=arg2;
beam_pc+=3;
execute_next();
}
put_var_X:
#if Debug
printf("%5d->put_var_X X%d,X%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
beam_X[arg1]=(Cell) beam_H;
beam_X[arg2]=(Cell) beam_H;
*(beam_H)=(Cell) beam_H;
beam_H++;
beam_pc+=3;
execute_next();
put_val_X:
#if Debug
printf("%5d->put_val_X X%d,X%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
beam_X[arg1]=beam_X[arg2];
beam_pc+=3;
execute_next();
put_var_P:
#if Debug
printf("%5d->put_var_P X%d,Y%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
if (isvar(beam_varlocals[arg2]) && !is_perm_var((Cell *) beam_varlocals[arg2]))
beam_varlocals[arg2]=(Cell) request_permVar(beam_ABX);
beam_X[arg1]=beam_varlocals[arg2];
beam_pc+=3;
execute_next();
put_var_Y:
/*
#if Debug
printf("%5d->put_var_Y X%d,Y%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
{ register Cell *a;
a = &(beam_varlocals[arg2]);
*a=(Cell) a;
beam_X[arg1]=(Cell) a; }
beam_pc+=3;
execute_next();
*/
put_val_Y:
#if Debug
printf("%5d->put_val_Y X%d,Y%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
beam_X[arg1]=beam_varlocals[arg2];
beam_pc+=3;
execute_next();
put_unsafe:
#if Debug
printf("%5d->put_unsafe X%d, Y%d \n",contador++,(int) arg1,(int) arg2);
break_debug(contador);
#endif
beam_X[arg1]=beam_varlocals[arg2];
beam_pc+=3;
execute_next();
put_atom:
#if Debug
printf("%5d->put_atom X%d, 0x%lX \n",contador++,(int) arg1,(unsigned long) arg2);
break_debug(contador);
#endif
beam_X[arg1]=arg2;
beam_pc+=3;
execute_next();
put_list:
#if Debug
printf("%5d->put_list X%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
{ register Cell *_DR1;
_DR1=(Cell *) abspair((Cell) beam_H); /* SaveExpression in _DR1*/
beam_X[arg1]=(Cell) _DR1;
beam_S=beam_H;
beam_H+=2;
beam_pc+=2;
execute_next();
}
put_struct:
#if Debug
printf("%5d->put_struct X%d, 0x%lX, %d \n",contador++,(int) arg1,(unsigned long) arg2,(int) arg3);
break_debug(contador);
#endif
{ register Cell _DR1;
_DR1=absappl((Cell) beam_H); /* SaveExpression in _DR1*/
beam_X[arg1]=(Cell) _DR1;
*(beam_H++)=arg2;
beam_S=beam_H;
beam_H+=arg3;
beam_pc+=4;
execute_next();
}
write_var_X:
#if Debug
printf("%5d->write_var_X X%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
*beam_S=(Cell) request_permVar(beam_ABX);
beam_X[arg1]=(Cell) beam_S;
beam_S++;
beam_pc+=2;
execute_next();
write_var_Y:
#if Debug
printf("%5d->write_var_Y Y%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
{ Cell *c;
c=&beam_varlocals[arg1];
*c=(Cell) c;
*beam_S=(Cell) c;
}
beam_S++;
beam_pc+=2;
execute_next();
write_var_P:
#if Debug
printf("%5d->write_var_P Y%d \n",contador++,(int) arg1);
break_debug(contador);
#endif
if (isvar(beam_varlocals[arg1]) && !is_perm_var((Cell *) beam_varlocals[arg1]))
beam_varlocals[arg1]=(Cell) request_permVar(beam_ABX);
*(beam_S)=beam_varlocals[arg1];
beam_S++;
beam_pc+=2;
execute_next();
write_local_X:
write_val_X:
#if Debug
printf("%5d->write_val_X X%d (or write_local)\n",contador++,(int) arg1);
break_debug(contador);
#endif
*(beam_S)=beam_X[arg1];
beam_S++;
beam_pc+=2;
execute_next();
write_local_Y:
write_val_Y:
#if Debug
printf("write_val_Y Y%d (or write_local)\n",(int) arg1);
#endif
*(beam_S)=beam_varlocals[arg1];
beam_S++;
beam_pc+=2;
execute_next();
write_void:
#if Debug
printf("%5d->write_void \n",contador++);
break_debug(contador);
#endif
*beam_S=(Cell) request_permVar(beam_ABX);
beam_S++;
beam_pc+=1;
execute_next();
write_atom:
#if Debug
printf("%5d->write_atom 0x%lX \n",contador++,(unsigned long) arg1);
break_debug(contador);
#endif
*(beam_S)=arg1;
beam_S++;
beam_pc+=2;
execute_next();
write_list:
#if Debug
printf("%5d->write_list \n",contador++);
break_debug(contador);
#endif
{ register Cell *_DR1;
_DR1=(Cell *) abspair((Cell) beam_H); /* SaveExpression in _DR1*/
*(beam_S++)=(Cell) _DR1;
push_mode_and_sreg();
beam_S=beam_H;
beam_H+=2;
beam_pc+=1;
execute_next();
}
write_last_list:
#if Debug
printf("%5d->write_last_list \n",contador++);
break_debug(contador);
#endif
{ register Cell *_DR1;
_DR1=(Cell *) abspair((Cell) beam_H); /* SaveExpression in _DR1*/
*(beam_S)=(Cell) _DR1;
beam_S=beam_H;
beam_H+=2;
beam_pc+=1;
execute_next();
}
write_struct:
#if Debug
printf("%5d->write_struct 0x%lX, %d \n",contador++,(unsigned long) arg1,(int) arg2);
break_debug(contador);
#endif
{ register Cell *_DR1;
_DR1=(Cell *) absappl((Cell) beam_H); /* SaveExpression in _DR1*/
*(beam_S++)=(Cell) _DR1;
push_mode_and_sreg();
*(beam_H++)=arg1;
beam_S=beam_H;
beam_H+=arg2;
beam_pc+=3;
execute_next();
}
write_last_struct:
#if Debug
printf("%5d->write_last_struct 0x%lX, %d \n",contador++,(unsigned long) arg1,(int) arg2);
break_debug(contador);
#endif
{ register Cell *_DR1;
_DR1=(Cell *) absappl((Cell) beam_H); /* SaveExpression in _DR1*/
*(beam_S)=(Cell) _DR1;
*(beam_H++)=arg1;
beam_S=beam_H;
beam_H+=arg2;
beam_pc+=3;
execute_next();
}
cut:
#if Debug
printf("%5d->cut na alternativa %p<> de %d \n",contador++,beam_ABX->nr_alternative, beam_ABX->parent->nr_all_alternatives);
break_debug(contador);
#endif
beam_OBX=beam_ABX->parent;
{
struct status_or *new;
if (!is_leftmost(beam_ABX,beam_nr_call)) {
#if Debug
printf("Force Waiting Before Cut\n");
#endif
beam_nr_call->call=NULL;
beam_nr_call->state=WAITING_TO_BE_LEFTMOST;
beam_ABX->suspended=addto_suspensions_list(beam_ABX,LEFTMOST_SUSPENSION);
beam_nr_call=beam_nr_call->next;
goto next_call;
}
beam_ABX->side_effects-=CUT;
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
#if Debug
printf("Executando o cut \n");
if (beam_ABX->externals!=NULL && beam_OBX->nr_all_alternatives>1) printf("cut com externals (noisy) \n");
if (beam_ABX->externals!=NULL && beam_OBX->nr_all_alternatives==1) printf("cut com externals (degenerate) \n");
#endif
beam_nr_alternative=beam_ABX->nr_alternative;
new=beam_nr_alternative->next;
beam_nr_alternative->next=NULL;
if (new!=NULL) {
do{
struct status_or *old;
old=new;
new=new->next;
del_andbox_and_sons(old->alternative);
if (new==NULL) remove_memory_arguments(old->args);
free_memory((Cell *) old,STATUS_OR_SIZE);
beam_OBX->nr_all_alternatives--;
} while (new!=NULL);
if (beam_OBX->nr_all_alternatives==1) {
beam_nr_alternative=beam_OBX->alternatives;
goto unique_alternative;
}
}
goto next_call;
}
commit:
#if Debug
printf("%5d->commit na alternativa %p<> de %d \n",contador++,beam_ABX->nr_alternative, beam_ABX->parent->nr_all_alternatives);
break_debug(contador);
#endif
beam_OBX=beam_ABX->parent;
{
struct status_or *new;
if (!is_leftmost(beam_OBX->parent,beam_OBX->nr_call)) {
#if Debug
printf("Force Waiting Before Commit\n");
#endif
beam_nr_call->call=NULL;
beam_nr_call->state=WAITING_TO_BE_LEFTMOST_PARENT;
beam_ABX->suspended=addto_suspensions_list(beam_ABX,LEFTMOST_SUSPENSION);
beam_nr_call=beam_nr_call->next;
goto next_call;
}
beam_ABX->side_effects-=CUT;
beam_nr_call=remove_call_from_andbox(beam_nr_call,beam_ABX);
#if Debug
printf("Executando o commit (apaga %d alternatives) \n",beam_OBX->nr_all_alternatives-1);
if (beam_ABX->externals!=NULL && beam_OBX->nr_all_alternatives>1) printf("commit com externals (noisy) \n");
if (beam_ABX->externals!=NULL && beam_OBX->nr_all_alternatives==1) printf("commit com externals (degenerate) \n");
#endif
if (beam_OBX->nr_all_alternatives>1) {
beam_nr_alternative=beam_ABX->nr_alternative;
beam_OBX->nr_all_alternatives=1;
new=beam_OBX->alternatives;
beam_OBX->alternatives=beam_nr_alternative; /* fica a ser a unica alternativa */
do {
struct status_or *old;
old=new;
new=new->next;
if (old!=beam_nr_alternative) {
del_andbox_and_sons(old->alternative);
if (new==NULL) remove_memory_arguments(old->args);
free_memory((Cell *) old,STATUS_OR_SIZE);
}
} while (new!=NULL);
beam_nr_alternative->next=NULL;
beam_nr_alternative->previous=NULL;
}
goto unique_alternative;
}
jump:
#if Debug
printf("%5d->jump inst %ld\n",contador++,(long int) arg1);
break_debug(contador);
#endif
beam_pc=(Cell *) arg1;
execute_next();
save_pair_Y:
#if Debug
printf("%5d->save_pair Y%ld\n",contador++,(long int) arg1);
break_debug(contador);
#endif
abort_eam("save_exp no emulador ?????");
--S;
beam_varlocals[arg1]=abspair(beam_S);
++S;
beam_pc+=2;
execute_next();
save_appl_Y:
#if Debug
printf("%5d->save_appl Y%ld\n",contador++,(long int) arg1);
break_debug(contador);
#endif
abort_eam("save_exp no emulador ?????");
--S;
beam_varlocals[arg1]=absappl(beam_S);
++S;
beam_pc+=2;
execute_next();
save_appl_X:
#if Debug
printf("%5d->save_appl X%ld\n",contador++,(long int) arg1);
break_debug(contador);
#endif
abort_eam("save_exp no emulador ?????");
--S;
beam_X[arg1]=absappl(beam_S);
++S;
beam_pc+=2;
execute_next();
save_pair_X:
#if Debug
printf("%5d->save_pair X%ld\n",contador++,(long int) arg1);
break_debug(contador);
#endif
abort_eam("save_exp no emulador ?????");
--S;
beam_X[arg1]=abspair(beam_S);
++S;
beam_pc+=2;
execute_next();
p_atom:
p_atomic:
p_integer:
p_nonvar:
p_number:
p_var:
p_db_ref:
p_primitive:
p_cut_by:
p_save_by:
p_succ:
p_predc:
p_plus:
p_minus:
p_times:
p_div:
p_equal:
p_dif:
p_eq:
p_arg:
p_functor:
abort_eam("std_pred no emulador ?????");
orelse:
orlast:
either:
abort_eam("either/orelse/orlast ainda nao implementadas ?????");
save_b_X:
save_b_Y:
comit_b_X:
comit_b_Y:
abort_eam("save_b_X/Y ou comit_b_X/Y no emulador ?????\n");
}
return (TRUE);
}
/* The Inst_am instruction is used in eamamasm.c */
Cell inst_am(int n);
Cell am_to_inst(Cell inst);
Cell inst_am(int n)
{
#if DIRECT_JUMP
if (TABLE_OPS==NULL) eam_am(NULL);
return TABLE_OPS[n];
#else
return(n);
#endif
}
Cell am_to_inst(Cell inst)
{
#if DIRECT_JUMP
int n;
for(n=0;n<=_p_functor; n++) if ((Cell) TABLE_OPS[n]==inst) return (n);
#endif
return(inst);
}
#if Debug_Dump_State
/************************************************************************\
* MORE DEBUG STUFF *
\************************************************************************/
#define DUMP_BOXES 0
#define DUMP_STATES 1
#define DUMP_VARS 2
void dump_eam_orbox(struct OR_BOX *o, struct AND_BOX *pai, struct status_and *pai2);
void dump_eam_andbox(struct AND_BOX *a, struct OR_BOX *pai, struct status_or *pai2);
char *SPACES(int level);
#define SPACE_MULT 4
char *SPACES(int level) {
static char spaces[2000];
int i;
for(i=0;i<level*SPACE_MULT;i++) {
spaces[i]=' ';
}
spaces[level*SPACE_MULT]=0;
return (spaces);
}
void dump_eam_state() {
static int nr_state=0;
int nr=0;
printf("State %d:\n",++nr_state);
/* verify suspended boxes */
if (beam_su!=NULL) {
struct SUSPENSIONS *s,*l;
l=beam_su->prev;
s=beam_su;
do {
nr++;
if (s->prev!=l) abort_eam("Invalid list of Suspended boxes\b");
l=s;
s=s->next;
} while(s!=beam_su);
}
printf("%d suspended boxes\n",nr);
dump_eam_andbox(beam_top,NULL, NULL);
}
void dump_eam_andbox(struct AND_BOX *a, struct OR_BOX *pai, struct status_or *pai2) {
struct status_and *calls, *last;
if (a==NULL) return;
if (pai!=a->parent) abort_eam("Pai diferente do parent\n");
if (pai2!=a->nr_alternative) abort_eam("Status call Pai diferente do nralternative\n");
if (a==beam_ABX) printf("->"); else printf(" ");
if (a->suspended) printf("*"); else printf(" ");
printf("%s+ANDBOX with %d goals\n",SPACES(2*(a->level)),a->nr_all_calls);
calls=a->calls;
last=NULL;
while(calls!=NULL) {
if (calls->previous!=last) abort_eam("link errado nos calls\n");
if (calls->locals==NULL) printf(" %sNO local vars\n",SPACES(2*(a->level)+1));
else printf(" %s%d local vars\n",SPACES(2*(a->level)+1),calls->locals[-1]);
if (calls->call==NULL) {
printf(" %s>ORBOX EMPTY\n",SPACES(2*(a->level)+1));
} else {
dump_eam_orbox(calls->call,a,calls);
}
last=calls;
calls=calls->next;
}
// printf("Exit from dum_eam_andbox\n");
}
void dump_eam_orbox(struct OR_BOX *o, struct AND_BOX *pai, struct status_and *pai2) {
struct status_or *i,*last;
if (o==NULL) return;
if (pai!=o->parent) abort_eam("Pai diferente do parent\n");
if (pai2!=o->nr_call) abort_eam("Status call Pai diferente do nrcall\n");
if (o==beam_OBX) printf("=> "); else printf(" ");
printf("%s>ORBOX with %d alternatives\n",SPACES(2*(o->parent->level)+1),o->nr_all_alternatives);
i=o->alternatives;
last=NULL;
while(i!=NULL) {
if (i->previous!=last) abort_eam("link errado nas alternativas\n");
if (i->args) {
printf(" %s+%d Arguments\n",SPACES(2*(o->parent->level+1)),i->args[0]);
if (i->args[0]<0 || i->args[0]>1000) abort_eam("Num Invalido de Args\n");
}
if (i->alternative==NULL) {
printf(" %s+ANDBOX EMPTY\n",SPACES(2*(o->parent->level+2)));
} else {
dump_eam_andbox(i->alternative,o, i);
}
last=i;
i=i->next;
}
}
#endif
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
int showTime(void) /* MORE PRECISION */
{
static int call_time=0;
static struct timeval StartTime;
static struct timezone TimeZone={0,0};
#if MICRO_TIME
if (!call_time) {
gettimeofday(&StartTime,&TimeZone);
call_time=1;
} else {
struct timeval time,diff;
call_time=0;
gettimeofday(&time,&TimeZone);
diff.tv_sec = time.tv_sec - StartTime.tv_sec;
diff.tv_usec = time.tv_usec - StartTime.tv_usec;
if(diff.tv_usec < 0){
diff.tv_usec += 1000000;
diff.tv_sec -= 1;
}
printf("CPU Time %ld (Microseconds)\n", (diff.tv_sec*1000000)+(diff.tv_usec));
}
return(TRUE);
#else
struct rusage rusage;
/* InitTime() and cputime() from sysbits.c */
if (!call_time) {
getrusage(RUSAGE_SELF, &rusage);
StartTime.tv_sec = rusage.ru_utime.tv_sec;
StartTime.tv_usec = rusage.ru_utime.tv_usec;
call_time=1;
} else {
struct timeval diff;
call_time=0;
getrusage(RUSAGE_SELF, &rusage);
diff.tv_sec = rusage.ru_utime.tv_sec - StartTime.tv_sec;
diff.tv_usec = rusage.ru_utime.tv_usec - StartTime.tv_usec;
if(diff.tv_usec < 0){
diff.tv_usec += 1000000;
diff.tv_sec -= 1;
}
printf("CPU Time %ld (Miliseconds)\n", (diff.tv_sec*1000)+(diff.tv_usec/1000));
}
return(TRUE);
#endif
}
#if USE_SPLIT
#include "eam_split.c"
#endif
#if GARBAGE_COLLECTOR
/************************************************************************\
* GC *
\************************************************************************/
#include "eam_gc.c"
#endif
#endif /* BEAM */