findall.c

00001 /* File:      findall.c
00002 ** Author(s): Bart Demoen
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** Copyright (C) ECRC, Germany, 1990
00007 ** 
00008 ** XSB is free software; you can redistribute it and/or modify it under the
00009 ** terms of the GNU Library General Public License as published by the Free
00010 ** Software Foundation; either version 2 of the License, or (at your option)
00011 ** any later version.
00012 ** 
00013 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00014 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00015 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00016 ** more details.
00017 ** 
00018 ** You should have received a copy of the GNU Library General Public License
00019 ** along with XSB; if not, write to the Free Software Foundation,
00020 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021 **
00022 ** $Id: findall.c,v 1.33 2005/12/12 18:44:52 dwarren Exp $
00023 ** 
00024 */
00025 
00026 
00027 #include "xsb_config.h"
00028 #include "xsb_debug.h"
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 
00033 #include "auxlry.h"
00034 #include "cell_xsb.h"        /* cell_xsb.h must be included before deref.h */
00035 #include "deref.h"
00036 #include "register.h"
00037 #include "memory_xsb.h"
00038 #include "psc_xsb.h"
00039 #include "error_xsb.h"
00040 #include "heap_xsb.h"
00041 #include "binding.h"
00042 #include "subp.h"
00043 #include "flags_xsb.h"
00044 #include "loader_xsb.h"
00045 #include "cinterf.h"
00046 #include "context.h"
00047 #include "findall.h"
00048 #include "thread_xsb.h"
00049 #include "debug_xsb.h"
00050 
00051 #ifndef MULTI_THREAD
00052 findall_solution_list *findall_solutions = NULL;
00053 findall_solution_list *current_findall;
00054 
00055 static int nextfree ; /* nextfree index in findall array */
00056 
00057 CPtr gl_bot, gl_top ;
00058 
00059 static f_tr_chunk *cur_tr_chunk ;
00060 static CPtr *cur_tr_top ;
00061 static CPtr *cur_tr_limit ;
00062 #endif
00063 
00064 extern void findall_free(CTXTdeclc int);
00065 extern int get_more_chunk(CTXTdecl);
00066 extern void findall_copy_to_heap(CTXTdeclc Cell, CPtr, CPtr *);
00067 extern int findall_init_c(CTXTdecl);
00068 
00069 #define MAX_FINDALLS  250
00070 /* make MAX_FINDALLS larger if you want */
00071 
00072 #define on_glstack(p) ((gl_bot <= p) && (p < gl_top))
00073 
00074 #include "ptoc_tag_xsb_i.h"
00075 
00076 /* malloc a new chunck and link it in in the current findall */
00077 int get_more_chunk(CTXTdecl)
00078 { CPtr newchunk ;
00079 
00080   if (!(newchunk = (CPtr)mem_alloc(FINDALL_CHUNCK_SIZE * sizeof(Cell),FINDALL_SPACE)))
00081     xsb_exit("get_more_chunk failed");
00082 
00083   *newchunk = 0 ;
00084   *(current_findall->current_chunk) = (Cell)newchunk ;
00085   current_findall->current_chunk = newchunk ;
00086   current_findall->top_of_chunk = newchunk + 1 ;
00087 
00088   return TRUE;
00089 
00090 } /*get_more_chunk*/
00091 
00092 /* $$findall_init/2
00093 
00094    to be called with 2 free variables
00095    the first variable is bound to an index in the findall table
00096    the second remains free - it will be set to 666 by findall_get_solutions
00097    without trailing, so that later add's will not occur
00098 */
00099 
00100 int findall_init_c(CTXTdecl)
00101 {
00102   CPtr w ;
00103   findall_solution_list *p ;
00104   int thisfree;
00105   
00106   if (findall_solutions == 0)
00107         { int i ;
00108           p = findall_solutions = (findall_solution_list *)
00109                         mem_alloc(MAX_FINDALLS*sizeof(findall_solution_list),FINDALL_SPACE) ;
00110           if (findall_solutions == 0)
00111             xsb_exit("init of findall failed") ;
00112           for (i = 0 ; i++ < MAX_FINDALLS ; p++)
00113                 { p->size = i ;
00114                   p->tail = 0 ;
00115                 }
00116           (--p)->size = -1 ;
00117           nextfree = 0 ;
00118         }
00119 
00120   if (nextfree < 0) /* could realloc here - too lazy to do it */
00121         xsb_abort("[FINDALL] Maximum number of active findalls reached");
00122   thisfree = nextfree;
00123         /* no checking - no trailing - just use findall_init correct :-) */
00124   p = findall_solutions + nextfree ;
00125   if (!(w = (CPtr)mem_alloc(FINDALL_CHUNCK_SIZE * sizeof(Cell),FINDALL_SPACE)))
00126         xsb_abort("[FINDALL] Not enough memory");
00127 
00128   *w = 0 ;
00129   p->first_chunk = p->current_chunk = w ;
00130   w++ ; bld_free(w) ; p->tail = w ; /* create an undef as init of tail */
00131   w++ ; p->top_of_chunk = w ;
00132   nextfree = p->size ;
00133   p->size = 1 ;
00134   return(thisfree) ;
00135 } /* findall_init_c */
00136 
00137 int findall_init(CTXTdecl)
00138 {
00139   Cell arg1 ;
00140   int ichunk;
00141  
00142   arg1 = ptoc_tag(CTXTc 1); 
00143   ichunk = findall_init_c(CTXT); 
00144   *(CPtr)arg1 = makeint(ichunk) ;
00145   return TRUE;
00146 } /* findall_init */
00147 
00148 /* findall_free is called to desactive an entry in the solution_list
00149    at the end of findall_get_solutions, and from findall_clean
00150 */
00151 
00152 void findall_free(CTXTdeclc int i)
00153 { CPtr to_free,p ;
00154 
00155   p = (findall_solutions + i)->first_chunk ;
00156   while (p != NULL)
00157         { to_free = p ; p = (CPtr)(*p) ; mem_dealloc(to_free,FINDALL_CHUNCK_SIZE * sizeof(Cell),FINDALL_SPACE) ; }
00158   (findall_solutions + i)->tail = 0 ;
00159   (findall_solutions + i)->size = nextfree ;
00160   nextfree = i ;
00161 } /*findall_free*/
00162 
00163 /* findall_clean should be called after interrupts or jumps out of the
00164    interpreter - or just before jumping back into it
00165 */
00166 
00167 void findall_clean(CTXTdecl)
00168 { findall_solution_list *p ;
00169   int i ;
00170         p = findall_solutions ;
00171         if (! p) return ;
00172         for (i = 0 ; i < MAX_FINDALLS ; i++)
00173                 { if (p->tail != 0)
00174                         findall_free(CTXTc i) ;
00175                   (findall_solutions + i)->size = i+1 ;
00176                 }
00177         (findall_solutions + i - 1)->size = -1 ;
00178         nextfree = 0 ;
00179 } /* findall_clean */
00180 
00181 /* findall_copy_to_heap does not need overflow checking - heap space is
00182    ensured; variables in the findall solution list can be altered without
00183    problem, because they are not needed afterwards anymore, so no trailing
00184 */
00185 
00186 void findall_copy_to_heap(CTXTdeclc Cell from, CPtr to, CPtr *h)
00187 {
00188 
00189 copy_again : /* for tail recursion optimisation */
00190 
00191   switch ( cell_tag( from ) )
00192     {
00193     case XSB_INT :
00194     case XSB_STRING :
00195       *to = from;
00196       return;
00197     case XSB_FLOAT :
00198 #ifndef FAST_FLOATS
00199       {
00200         Float tempFloat = getfloatval(from);
00201         new_heap_functor((*h),box_psc);
00202         bld_int((*h),((ID_BOXED_FLOAT << BOX_ID_OFFSET ) | FLOAT_HIGH_16_BITS(tempFloat) ));
00203         (*h)++;
00204         bld_int((*h),FLOAT_MIDDLE_24_BITS(tempFloat)); (*h)++;
00205         bld_int((*h),FLOAT_LOW_24_BITS(tempFloat)); (*h)++;
00206         cell(to) = makecs((*h)-4);
00207       }
00208 #else
00209       *to = from;
00210 #endif
00211       return;
00212     case XSB_REF :
00213     case XSB_REF1 :
00214       XSB_Deref(from);
00215       if (! isref(from)) goto copy_again; /* it could be a XSB_LIST */
00216       if (on_glstack((CPtr)(from)))
00217         *to = from;
00218       else
00219         {
00220           *(CPtr)from = (Cell)to;
00221           *to = (Cell)to;
00222         }
00223       return;
00224 
00225   case XSB_LIST :
00226     {
00227       CPtr pfirstel;
00228       Cell q ;
00229 
00230       /* first test whether from - which is an L - is actually the left over
00231          of a previously copied first list element
00232       */
00233       pfirstel = clref_val(from) ;
00234       if (on_glstack(pfirstel))
00235         {
00236           /* pick up the old value and copy it */
00237           *to = *pfirstel;
00238           return;
00239         }
00240 
00241       q = *pfirstel;
00242       if (islist(q))
00243         {
00244           CPtr p;
00245           
00246           p = clref_val(q);
00247           if (on_glstack(p))  /* meaning it is a shared list */
00248             {
00249               *to = q;
00250               return;
00251             }
00252         }
00253 
00254 
00255 
00256       /* this list cell has not been copied before */
00257       /* now be careful: if the first element of the list to be copied
00258            is an undef (a ref to an undef is not special !)
00259            we have to copy this undef now, before we do the general
00260            thing for lists
00261       */
00262 
00263       {
00264         Cell tr1;
00265 
00266         tr1 = *to = makelist(*h) ;
00267         to = (*h) ;
00268         (*h) += 2 ;
00269         if (q == (Cell)pfirstel) /* it is an UNDEF - special care needed */
00270           {
00271             /* it is an undef in the part we are copying from */
00272             *to = (Cell)to ;
00273             *pfirstel = makelist((CPtr)to);
00274           }
00275         else
00276           {
00277             *pfirstel = makelist((CPtr)to);
00278             findall_copy_to_heap(CTXTc q,to,h);
00279           }
00280 
00281         from = *(pfirstel+1) ; to++ ;
00282         goto copy_again ;
00283       }
00284     }
00285 
00286     case XSB_STRUCT :
00287       {
00288         CPtr pfirstel;
00289         Cell newpsc;
00290         int ar;
00291     
00292         pfirstel = (CPtr)cs_val(from);
00293         if ( cell_tag((*pfirstel)) == XSB_STRUCT )
00294           {
00295             /* this struct was copied before - it must be shared */
00296             *to = *pfirstel;
00297             return;
00298           }
00299 
00300         /* first time we visit this struct */
00301       
00302         ar = get_arity((Psc)(*pfirstel)) ;
00303         
00304         newpsc = *to = makecs((Cell)(*h)) ;
00305         to = *h ;
00306         *to = *pfirstel ; /* the functor */
00307         *pfirstel = newpsc; /* no need for trailing */
00308         
00309         *h += ar + 1 ;
00310         while ( --ar )
00311           {
00312             from = *(++pfirstel) ; to++ ;
00313             findall_copy_to_heap(CTXTc from,to,h) ;
00314           }
00315         from = *(++pfirstel) ; to++ ;
00316         goto copy_again ;
00317       }
00318   
00319   case XSB_ATTV: {
00320     CPtr var;
00321     
00322     /*
00323      * The following XSB_Deref() is necessary, because, in copying
00324      * f(X,X), after the first occurrence of X is copied, the VAR
00325      * part of X has been pointed to the new copy on the heap.  When
00326      * we see this X again, we should dereference it to find that X
00327      * is already copied, but this deref is not done (see the code
00328      * in `case XSB_STRUCT:' -- deref's are gone).
00329      */
00330     XSB_Deref(from);
00331     var = clref_val(from);  /* the VAR part of the attv  */
00332     if (on_glstack(var))    /* is a new attv in the `to area' */
00333       bld_attv(to, var);
00334     else {                /* has not been copied before */
00335       from = cell(var + 1); /* from -> the ATTR part of the attv */
00336       XSB_Deref(from);
00337       *to = makeattv(*h);
00338       to = (*h);
00339       (*h) += 2;                  /* skip two cells */
00340       /*
00341        * Trail and bind the VAR part of the attv to the new attv
00342        * just created in the `to area', so that attributed variables
00343        * are shared in the `to area'.
00344        */
00345       bld_attv(var, to);
00346       cell(to) = (Cell) to;
00347       to++;
00348       goto copy_again;
00349     }
00350   } /* case XSB_ATTV */
00351   }
00352  
00353 } /*findall_copy_to_heap*/
00354 
00355 
00356 /* trailing variables during copying a template: a linked list of arrays is used */
00357 
00358 static void findall_untrail(CTXTdecl)
00359 {
00360   CPtr *p, *begin_trail ;
00361   f_tr_chunk *tr_chunk, *tmp ;
00362   
00363   if( !(tr_chunk = cur_tr_chunk) ) return ; /* protection */
00364   begin_trail = tr_chunk->tr ;
00365   
00366   for (p = cur_tr_top ; p-- > begin_trail ; )
00367     {
00368       *((CPtr)(*p)) = (Cell)(*(p-1));
00369       p--;
00370     }
00371   
00372   tmp = tr_chunk ; tr_chunk = tr_chunk->previous ; mem_dealloc(tmp,sizeof(f_tr_chunk),FINDALL_SPACE) ;
00373   while (tr_chunk != 0)
00374     {
00375       begin_trail = tr_chunk->tr ;
00376       for (p = tr_chunk->tr + F_TR_NUM; p-- > begin_trail ; )
00377         {
00378           *((CPtr)(*p)) = (Cell)(*(p-1));
00379           p--;
00380         }
00381       tmp = tr_chunk ; tr_chunk = tr_chunk->previous ; mem_dealloc(tmp,sizeof(f_tr_chunk),FINDALL_SPACE) ;
00382     }
00383 } /* findall_untrail */
00384 
00385 /* if tr2 == 0, then we need to trail only the first two */
00386 
00387 static int findall_trail(CTXTdeclc CPtr p, Cell val)
00388 { 
00389   f_tr_chunk *new_tr_chunk ;
00390   int trail_left = cur_tr_limit - cur_tr_top;
00391   
00392   if (trail_left == 0)
00393     {
00394       if (!(new_tr_chunk = (f_tr_chunk *)mem_alloc(sizeof(f_tr_chunk),FINDALL_SPACE)))
00395         xsb_exit("findall_trail failed");
00396       cur_tr_top = new_tr_chunk->tr ;
00397       cur_tr_limit = new_tr_chunk->tr+F_TR_NUM ;
00398       new_tr_chunk->previous = cur_tr_chunk ;
00399       cur_tr_chunk = new_tr_chunk ;
00400     }
00401 
00402   *(cur_tr_top++) = (CPtr)val;
00403   *(cur_tr_top++) = (CPtr)p;
00404   return TRUE;
00405 } /* findall_trail */
00406 
00407 static int init_findall_trail(CTXTdecl)
00408 {
00409   if (!(cur_tr_chunk = (f_tr_chunk *)mem_alloc(sizeof(f_tr_chunk),FINDALL_SPACE)))
00410     xsb_exit("init_findall_trail failed");
00411   cur_tr_top = cur_tr_chunk->tr ;
00412   cur_tr_limit = cur_tr_chunk->tr+F_TR_NUM ;
00413   cur_tr_chunk->previous = 0 ;
00414   return TRUE;
00415 } /* init_findall_trail */
00416 
00417 /* findall_copy_template_to_chunk
00418    must do: overflow checking
00419    trailing of variables
00420    returns size of copied term
00421    if it "fails", returns a negative number
00422 */
00423 
00424 static int findall_copy_template_to_chunk(CTXTdeclc Cell from, CPtr to, CPtr *h)
00425 {
00426   int size = 0 ;
00427   int s ;
00428 
00429   copy_again : /* for tail recursion optimisation */
00430 
00431     switch ( cell_tag( from ) )
00432       {
00433       case XSB_INT :
00434       case XSB_FLOAT :
00435       case XSB_STRING :
00436         *to = from ;
00437         return(size) ;
00438     
00439       case XSB_REF :
00440       case XSB_REF1 :
00441         if (on_glstack((CPtr)(from)))
00442           {
00443             findall_trail(CTXTc (CPtr)from,from) ;
00444             *(CPtr)from = (Cell)to ;
00445             *to = (Cell)to ;
00446           } else *to = from ;
00447         return(size) ;
00448 
00449       case XSB_LIST :
00450         {
00451           CPtr pfirstel ;
00452           Cell q ;
00453 
00454           /* first test whether from - which is an L - is actually the left over
00455              of a previously copied first list element
00456           */
00457           pfirstel = clref_val(from) ;
00458           if (! on_glstack(pfirstel))
00459             {
00460               /* pick up the old value and copy it */
00461               *to = *pfirstel;
00462               return(size);
00463             }
00464           
00465           q = *pfirstel;
00466           if (islist(q))
00467             {
00468               CPtr p;
00469               
00470               p = clref_val(q);
00471               if (! on_glstack(p))
00472                 {
00473                   *to = q;
00474                   return(size);
00475                 }
00476             }
00477 
00478           if (*h > (current_findall->current_chunk + FINDALL_CHUNCK_SIZE - 3))
00479             {
00480               if (! get_more_chunk(CTXT)) return(-1) ;
00481               *h = current_findall->top_of_chunk ;
00482             }
00483 
00484           {
00485             Cell tr1;
00486 
00487             tr1 = *to = makelist(*h) ;
00488             to = (*h) ;
00489             (*h) += 2 ;
00490             if (q == (Cell)pfirstel) /* it is an UNDEF - special care needed */
00491               {
00492                 /* it is an undef in the part we are copying from */
00493                 findall_trail(CTXTc pfirstel,(Cell)pfirstel);
00494                 *to = (Cell)to ;
00495                 *pfirstel = makelist((CPtr)to);
00496               }
00497             else
00498               {
00499                 findall_trail(CTXTc pfirstel,q);
00500                 *pfirstel = makelist((CPtr)to);
00501                 XSB_Deref(q);
00502                 s = findall_copy_template_to_chunk(CTXTc q,to,h);
00503                 if (s < 0) return(-1) ;
00504                 size += s + 2 ;
00505               }
00506 
00507             from = *(pfirstel+1) ; XSB_Deref(from) ; to++ ;
00508             goto copy_again ;
00509           }
00510         }
00511         
00512       case XSB_STRUCT :
00513         {
00514           CPtr pfirstel ;
00515           Cell newpsc;
00516           int ar ;
00517     
00518           pfirstel = (CPtr)cs_val(from) ;
00519           if ( cell_tag((*pfirstel)) == XSB_STRUCT )
00520             {
00521               /* this struct was copied before - it must be shared */
00522               *to = *pfirstel;
00523               return(size);
00524             }
00525 
00526           /* first time we visit this struct */
00527 
00528           findall_trail(CTXTc pfirstel,*pfirstel);
00529 
00530           ar = get_arity((Psc)(*pfirstel)) ;
00531           /* make sure there is enough space in the chunks */
00532           if (*h > (current_findall->current_chunk + FINDALL_CHUNCK_SIZE - 1 - ar))
00533             {
00534               if (! get_more_chunk(CTXT)) return(-1) ;
00535               *h = current_findall->top_of_chunk ;
00536             }
00537 
00538           newpsc = *to = makecs((Cell)(*h)) ;
00539           to = *h ;
00540           *to = *pfirstel ; /* the functor */
00541           *pfirstel = newpsc; /* was trailed already */
00542 
00543           *h += ar + 1 ;
00544           size += ar + 1 ;
00545           while ( --ar )
00546             {
00547               from = *(++pfirstel) ; XSB_Deref(from) ; to++ ;
00548               s = findall_copy_template_to_chunk(CTXTc from,to,h) ;
00549               if (s < 0) return(-1) ;
00550               size += s ;
00551             }
00552           from = *(++pfirstel) ; XSB_Deref(from) ; to++ ;
00553           goto copy_again ;
00554         }
00555   
00556   case XSB_ATTV: {
00557     CPtr var;
00558     
00559     var = clref_val(from);  /* the VAR part of the attv  */
00560     if (on_glstack(var)) {  /* has not been copied before */
00561       from = cell(var + 1); /* from -> the ATTR part of the attv */
00562       XSB_Deref(from);
00563       if (*h > (current_findall->current_chunk + FINDALL_CHUNCK_SIZE - 3)) {
00564         if (! get_more_chunk(CTXT)) return(-1) ;
00565         *h = current_findall->top_of_chunk ;
00566       }
00567       *to = makeattv(*h);
00568       to = (*h);
00569       (*h) += 2;                  /* skip two cells */
00570       size += 2;
00571       /*
00572        * Trail and bind the VAR part of the attv to the new attv
00573        * just created in the `to area', so that attributed variables
00574        * are shared in the `to area'.
00575        */
00576       findall_trail(CTXTc var,(Cell)var);
00577       bld_attv(var, to);
00578       cell(to) = (Cell) to;
00579       to++;
00580       goto copy_again;
00581     }
00582     else {                /* is a new attv in the `to area' */
00583       bld_attv(to, var);
00584       return(size);
00585     }
00586   } /* case XSB_ATTV */
00587   } /* switch */
00588  
00589  return(-1) ; /* to keep compiler happy */
00590  
00591 } /*findall_copy_template_to_chunk */
00592 
00593 /*
00594   $$findall_add/3
00595   arg1 : any
00596   arg2 : findall index - where to add it
00597   arg3 : if not var, then return with fail immediately
00598   at arg2, the term arg1 is added to the solution list
00599   if findall_add/2 fails, the associated term remains unchanged
00600 */
00601 
00602 int findall_add(CTXTdecl)
00603 {
00604   Cell arg1, arg2, arg3 ;
00605   CPtr to, h ;
00606   int size ;
00607   
00608   arg3 = ptoc_tag(CTXTc 3);
00609   {
00610     int t = cell_tag(arg3) ;
00611     if ((t != XSB_REF) && (t != XSB_REF1)) return(0) ;
00612   }
00613   
00614   arg1 = ptoc_tag(CTXTc 1);
00615   arg2 = ptoc_tag(CTXTc 2);
00616   
00617   current_findall = findall_solutions + int_val(arg2) ;
00618   if (current_findall->tail == 0)
00619     xsb_exit("internal error 1 in findall") ;
00620   
00621   to = current_findall->top_of_chunk ;
00622   if ((to+2) > (current_findall->current_chunk + FINDALL_CHUNCK_SIZE -1)) {
00623     if (! get_more_chunk(CTXT)) return(0) ;
00624     to = current_findall->top_of_chunk ;
00625   }
00626   
00627   h = to + 2 ;
00628   gl_bot = (CPtr)glstack.low ; gl_top = (CPtr)glstack.high ;
00629   
00630   if (init_findall_trail(CTXT) &&
00631       (0 <= (size = findall_copy_template_to_chunk(CTXTc arg1,to,&h)))) {
00632     findall_untrail(CTXT) ;
00633     current_findall->top_of_chunk = h ;
00634     /* 2 because of ./2 of solution list */
00635     current_findall->size += size + 2 ;
00636     bld_free((to+1)) ;
00637     /* link in new template now */
00638     *(CPtr)(*(current_findall->tail)) = makelist(to);
00639     current_findall->tail = to+1 ; /* fill in new tail */
00640     return TRUE;
00641   }
00642   
00643   findall_untrail(CTXT) ;
00644   return FALSE;
00645 } /* findall_add */
00646 
00647 /* $$findall_get_solutions/4
00648    arg1 : out : solution list of findall
00649    arg2 : out : tail of the list
00650    arg3 : in : integer = findall index
00651    arg4 : a variable which is now destructively set to 666
00652    
00653    the list at arg3 is copied to the heap and then this copy is unified with
00654    arg1-arg2 
00655 */
00656 
00657 int findall_get_solutions(CTXTdecl)
00658 {
00659   Cell arg1, arg2, arg3, arg4, from ;
00660   int cur_f ;
00661   findall_solution_list *p ;
00662   
00663   arg4 = ptoc_tag(CTXTc 4);
00664   {
00665     int t = cell_tag(arg4) ;
00666     if ((t == XSB_REF) || (t == XSB_REF1)) *(CPtr)arg4 = makeint(666) ;
00667   }
00668   
00669   arg3 = ptoc_tag(CTXTc 3); 
00670   cur_f = int_val(arg3) ;
00671   
00672   p = findall_solutions + cur_f ;
00673   
00674   check_glstack_overflow(4, pcreg, p->size*sizeof(Cell)) ;
00675   
00676   arg1 = ptoc_tag(CTXTc 1);  /* only after enough space is ensured */
00677   arg2 = ptoc_tag(CTXTc 2);  /* only after enough space is ensured */
00678   
00679   gl_bot = (CPtr)glstack.low ; gl_top = (CPtr)glstack.high ;
00680   
00681   from = *(p->first_chunk+1) ; /* XSB_Deref not necessary */
00682   findall_copy_to_heap(CTXTc from,(CPtr)arg1,&hreg) ; /* this can't fail */
00683   *(CPtr)arg2 = *(p->tail) ; /* no checking, no trailing */
00684   findall_free(CTXTc cur_f) ;
00685   return TRUE;
00686 } /* findall_get_solutions */
00687 
00688 /* adapted from findall_copy_template_to_chunck */
00689 /* returns the number of cells needed for the construction of term */
00690 static long term_size(CTXTdeclc Cell term)
00691 {
00692   long size = 0 ;
00693  recur:
00694   switch(cell_tag(term)) {
00695   case XSB_FREE:
00696   case XSB_REF1:
00697   case XSB_INT:
00698   case XSB_STRING:
00699   case XSB_FLOAT:
00700     return size ;
00701   case XSB_LIST: {
00702     CPtr pfirstel ;
00703     
00704     pfirstel = clref_val(term) ;
00705     term = *pfirstel ; XSB_Deref(term) ;
00706     size += 2 + term_size(CTXTc term) ;
00707     term = *(pfirstel+1) ; XSB_Deref(term) ;
00708     goto recur;
00709   }
00710   case XSB_STRUCT: {
00711     int a ;
00712     CPtr pfirstel ;
00713     
00714     pfirstel = (CPtr)cs_val(term) ;
00715     a = get_arity((Psc)(*pfirstel)) ;
00716     size += a + 1 ;
00717     while( --a ) {
00718       term = *++pfirstel ; XSB_Deref(term) ;
00719       size += term_size( CTXTc term ) ;
00720     }
00721     term = *++pfirstel ; XSB_Deref(term) ;
00722     goto recur;
00723   }
00724   case XSB_ATTV: {
00725     CPtr pfirstel;
00726 
00727     pfirstel = clref_val(term);
00728     if (pfirstel < hreg) {
00729       /*
00730        * This is the first occurrence of an attributed variable.  Its
00731        * first cell (the VAR part) will be changed to an XSB_ATTV cell which
00732        * points to hreg, and the cell of hreg will be set to a free
00733        * variable.  So the later occurrence of this attributed variable is
00734        * dereferenced and seen as an XSB_ATTV pointing to hreg, and we can
00735        * tell it has been counted before.
00736        */
00737       size += 2;
00738       findall_trail(CTXTc pfirstel,(Cell)pfirstel);
00739       bld_attv(pfirstel, hreg); /* bind VAR part to a cell out of hreg */
00740       bld_free(hreg);
00741       term = cell(clref_val(term) + 1);
00742       goto recur;
00743     }
00744     else /* this XSB_ATTV has been counted before */
00745       return size;
00746   }
00747   }
00748   return FALSE;
00749 }
00750 
00751 /* rewritten */
00752 /* recursively copies a term to a area of memory */
00753 /* used by copy_term to build a variant in the heap */
00754 
00755 static void do_copy_term(CTXTdeclc Cell from, CPtr to, CPtr *h)
00756 {
00757 copy_again : /* for tail recursion optimisation */
00758 
00759   switch ( cell_tag( from ) )
00760     {
00761     case XSB_INT :
00762     case XSB_FLOAT :
00763     case XSB_STRING :
00764       *to = from ;
00765       return ;
00766     
00767     case XSB_REF :
00768     case XSB_REF1 :
00769       if ((CPtr)from < hreg)  /* meaning: a not yet copied undef */
00770         {
00771           findall_trail(CTXTc (CPtr)from,from) ;
00772           *(CPtr)from = (Cell)to ;
00773           *to = (Cell)to ;
00774         }
00775       else *to = from ;
00776       return ;
00777 
00778     case XSB_LIST :
00779       {
00780         /*
00781          *  before copying:
00782          *  
00783          *  +----+        +----+----+
00784          *  | x L|    (x) | a  | b  |    empty trail
00785          *  +----+        +----+----+
00786          *  
00787          *  
00788          *  after copying:
00789          *  
00790          *  
00791          *  +----+        +----+----+
00792          *  | x L|    (x) | x'L| b  |
00793          *  +----+        +----+----+
00794          *  
00795          *  
00796          *  trail:
00797          *  
00798          *  +----+----+
00799          *  | a  | x  |
00800          *  +----+----+
00801          *  
00802          *  
00803          *  the copy is:
00804          *  
00805          *  +----+         +----+----+
00806          *  | x'L|    (x') | a' | b' |
00807          *  +----+         +----+----+
00808          *  
00809          *  careful if a is undef !
00810          */
00811 
00812         CPtr pfirstel;
00813         Cell q ;
00814 
00815         /* first test whether from - which is an L - is actually the left over
00816            of a previously copied first list element
00817         */
00818         pfirstel = clref_val(from) ;
00819         if (pfirstel >= hreg)
00820           {
00821             /* pick up the old value and copy it */
00822             *to = *pfirstel;
00823             return;
00824           }
00825 
00826         q = *pfirstel;
00827         if (islist(q))
00828           {
00829             CPtr p;
00830 
00831             p = clref_val(q);
00832             if (p >= hreg)  /* meaning it is a shared list */
00833               {
00834                 *to = q;
00835                 return;
00836               }
00837           }
00838 
00839         /* this list cell has not been copied before */
00840         /* now be careful: if the first element of the list to be copied
00841            is an undef (a ref to an undef is not special !)
00842            we have to copy this undef now, before we do the general
00843            thing for lists
00844         */
00845 
00846         {
00847           Cell tr1;
00848 
00849           tr1 = *to = makelist(*h) ;
00850           to = (*h) ;
00851           (*h) += 2 ;
00852           if (q == (Cell)pfirstel) /* it is an UNDEF - special care needed */
00853             {
00854               /* it is an undef in the part we are copying from */
00855               findall_trail(CTXTc pfirstel,(Cell)pfirstel);
00856               *to = (Cell)to ;
00857               *pfirstel = makelist((CPtr)to);
00858             }
00859           else
00860             {
00861               findall_trail(CTXTc pfirstel,q);
00862               *pfirstel = makelist((CPtr)to);
00863               XSB_Deref(q);
00864               do_copy_term(CTXTc q,to,h);
00865             }
00866 
00867           from = *(pfirstel+1) ; XSB_Deref(from) ; to++ ;
00868           goto copy_again ;
00869         }
00870       }
00871 
00872     case XSB_STRUCT : {
00873       /*
00874        before copying:
00875        
00876            +--------+     +-----------------------------------+      +--------+
00877        (b) |a STRUCT| (a) | Functor | arg1 | arg2 | ... | argn|  (f) |a STRUCT|
00878            +--------+     +-----------------------------------+      +--------+
00879        
00880        trail stack empty
00881        
00882        after copying the first (at b)
00883        
00884        
00885            +--------+     +------------------------------------+     +--------+
00886        (b) |a STRUCT| (a) | d STRUCT | arg1 | arg2 | ... | argn| (f) |a STRUCT|
00887            +--------+     +------------------------------------+     +--------+
00888                        
00889            +--------+      +-----------------------------------+ 
00890        (c) |d STRUCT|  (d) | Functor | arg1 | arg2 | ... | argn| 
00891            +--------+      +-----------------------------------+ 
00892        
00893               +-------------+
00894        trail: | Functor | a |
00895               +-------------+
00896         
00897        c and d are addresses of the copied things
00898        
00899        so when we come at the STRUCT pointer at f, we hit the |d STRUCT| cell
00900        at a, which means that it was copied before
00901         
00902        this relies on a Functor cell not having a STRUCT tag
00903         
00904        the situation for lists is more complicated
00905       */
00906       
00907         CPtr pfirstel ;
00908         Cell newpsc;
00909         int ar ;
00910 
00911         pfirstel = (CPtr)cs_val(from) ;
00912         if ( cell_tag((*pfirstel)) == XSB_STRUCT )
00913           {
00914             /* this struct was copied before - it must be shared */
00915             *to = *pfirstel;
00916             return;
00917           }
00918 
00919         /* first time we visit this struct */
00920 
00921         findall_trail(CTXTc pfirstel,*pfirstel);
00922 
00923         ar = get_arity((Psc)(*pfirstel)) ;
00924         
00925         newpsc = *to = makecs((Cell)(*h)) ;
00926         to = *h ;
00927         *to = *pfirstel ; /* the functor */
00928         *pfirstel = newpsc; /* was trailed already */
00929         
00930         *h += ar + 1 ;
00931         while ( --ar )
00932           {
00933             from = *(++pfirstel) ; XSB_Deref(from) ; to++ ;
00934             do_copy_term(CTXTc from,to,h) ;
00935           }
00936         from = *(++pfirstel) ; XSB_Deref(from) ; to++ ;
00937         goto copy_again ;
00938       }
00939 
00940     case XSB_ATTV:
00941       {
00942         /*
00943          *  before copying: (A means XSB_ATTV tag)
00944          *  
00945          *  +----+        +----+----+
00946          *  | x A|    (x) | a  | b  |    empty trail
00947          *  +----+        +----+----+
00948          *  
00949          *  because of deref, a is always an undef, meaning that actually
00950          *  a == x
00951          *  
00952          *  
00953          *  after copying:
00954          *  
00955          *  
00956          *  +----+        +----+----+
00957          *  | x A|    (x) | x'A| b  |
00958          *  +----+        +----+----+
00959          *  
00960          *  
00961          *  trail:
00962          *  
00963          *  +----+----+
00964          *  | x  | x  |
00965          *  +----+----+
00966          *  
00967          *  the copy is:
00968          *  
00969          *  +----+         +----+----+
00970          *  | x'A|    (x') | a' | b' |
00971          *  +----+         +----+----+
00972          */
00973 
00974         CPtr var;
00975     
00976         var = clref_val(from);  /* the VAR part of the attv  */
00977         if (var < hreg) {       /* has not been copied before */
00978           from = cell(var + 1); /* from -> the ATTR part of the attv */
00979           XSB_Deref(from);
00980           *to = makeattv(*h);
00981           to = (*h);
00982           (*h) += 2;            /* skip two cells */
00983           /*
00984            * Trail and bind the VAR part of the attv to the new attv just
00985            * created in the `to area', so that attributed variables are
00986            * shared in the `to area'.
00987            */
00988           findall_trail(CTXTc var,(Cell)var);
00989           bld_attv(var, to);
00990           cell(to) = (Cell) to;
00991           to++;
00992           goto copy_again;
00993         } else                  /* is a new attv in the `to area' */
00994           bld_attv(to, var);
00995       } /* case XSB_ATTV */
00996     } /* switch */
00997 } /* do_copy_term */
00998 
00999 
01000 
01001 /* creates a new variant of a term in the heap
01002    arg1 - old term
01003    arg2 - new term; copy of old term unifies with new term
01004 */
01005 
01006 int copy_term(CTXTdecl)
01007 {
01008   long size ;
01009   Cell arg1, arg2, to ;
01010   CPtr hptr ;
01011 
01012   arg1 = ptoc_tag(CTXTc 1);
01013   
01014   if( isref(arg1) ) return 1;
01015 
01016   init_findall_trail(CTXT) ;
01017   size = term_size(CTXTc arg1) ;
01018   findall_untrail(CTXT) ;
01019 
01020   check_glstack_overflow( 2, pcreg, size*sizeof(Cell)) ;
01021   
01022   /* again because stack might have been reallocated */
01023   arg1 = ptoc_tag(CTXTc 1);
01024   arg2 = ptoc_tag(CTXTc 2);
01025   
01026   hptr = hreg ;
01027   
01028   gl_bot = (CPtr)glstack.low ; gl_top = (CPtr)glstack.high ;
01029   init_findall_trail(CTXT) ;
01030   do_copy_term( CTXTc arg1, &to, &hptr ) ;
01031   findall_untrail(CTXT) ;
01032   
01033   {
01034     int size2 = hptr - hreg;
01035     /* fprintf(stderr,"copied size = %d\n",size2); */
01036     if (size2 > size)
01037       fprintf(stderr,"panic after copy_term\n");
01038   }
01039 
01040   hreg = hptr;
01041 
01042   return(unify(CTXTc arg2, to));
01043 } /* copy_term */
01044 
01045 void mark_findall_strings(CTXTdecl) {
01046   int i;
01047   CPtr chunk;
01048   CPtr cell;
01049 
01050   if (findall_solutions == 0) return;
01051   for (i = 0; i < MAX_FINDALLS; i++) {
01052     chunk = (findall_solutions+i)->first_chunk;
01053     if ((findall_solutions+i)->tail != 0) {
01054       while (chunk != (findall_solutions+i)->current_chunk) {
01055         for (cell=chunk+1; cell<(chunk+FINDALL_CHUNCK_SIZE); cell++) {
01056           mark_if_string(*cell,"findall");
01057         }
01058         chunk = *(CPtr *)chunk;
01059       }
01060       for (cell=chunk+1; cell<(findall_solutions+i)->top_of_chunk; cell++) {
01061         mark_if_string(*cell,"findall");
01062       }
01063     }
01064   }
01065 }
01066 
01067 /* Copies a term from another thread's stack
01068  * Source thread hreg is used to make do_copy_term work properly
01069  */
01070 #ifdef MULTI_THREAD
01071 Cell copy_term_from_thread( th_context *th, th_context *from, Cell arg1 )
01072 {
01073   CPtr hptr ;
01074   Cell to ;
01075 
01076   hptr = hreg ;
01077   hreg = from->_hreg ;
01078   init_findall_trail(CTXT) ;
01079   do_copy_term( th, arg1, &to, &hptr ) ;
01080   findall_untrail(CTXT) ;
01081 
01082   hreg = hptr ;
01083 
01084   return to ;
01085 }
01086 #endif
01087 

Generated on Wed Jul 26 13:30:40 2006 for XSB by  doxygen 1.4.5