slgdelay.c

00001 /* File:      slgdelay.c
00002 ** Author(s): Kostis Sagonas, Baoqiu Cui
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: slgdelay.c,v 1.47 2006/03/18 17:37:49 tswift 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 /* special debug includes */
00034 #include "debugs/debug_delay.h"
00035 
00036 #include "auxlry.h"
00037 #include "cell_xsb.h"
00038 #include "psc_xsb.h"
00039 #include "register.h"
00040 #include "trie_internals.h"
00041 #include "memory_xsb.h"
00042 #include "choice.h"
00043 #include "macro_xsb.h"
00044 #include "tr_utils.h"
00045 #include "inst_xsb.h"
00046 #include "error_xsb.h"
00047 #include "io_builtins_xsb.h"
00048 #include "thread_xsb.h"
00049 
00050 static void simplify_neg_succeeds(CTXTdeclc VariantSF);
00051 extern void simplify_pos_unsupported(CTXTdeclc NODEptr);
00052 static void simplify_pos_unconditional(CTXTdeclc NODEptr);
00053 
00054 /*
00055  * Some new global variables ...
00056  */
00057 
00058 /* Constants */
00059 static unsigned long de_block_size_glc = 2048 * sizeof(struct delay_element);
00060 static unsigned long dl_block_size_glc = 2048 * sizeof(struct delay_list);
00061 static unsigned long pnde_block_size_glc = 2048 *sizeof(struct pos_neg_de_list);
00062 
00063 /* Rest of globals protected by MUTEX_DELAY (I hope) */
00064 static char *current_de_block_gl = NULL;
00065 static char *current_dl_block_gl = NULL;
00066 static char *current_pnde_block_gl = NULL;
00067 
00068 static DE released_des_gl = NULL;       /* the list of released DEs */
00069 static DL released_dls_gl = NULL;       /* the list of released DLs */
00070 static PNDE released_pndes_gl = NULL;   /* the list of released PNDEs */
00071 
00072 static DE next_free_de_gl = NULL;       /* next available free DE space */
00073 static DL next_free_dl_gl = NULL;       /* next available free DL space */
00074 static PNDE next_free_pnde_gl = NULL;   /* next available free PNDE space */
00075 
00076 static DE current_de_block_top_gl = NULL;      /* the top of current DE block */
00077 static DL current_dl_block_top_gl = NULL;      /* the top of current DL block */
00078 static PNDE current_pnde_block_top_gl = NULL; /* the top of current PNDE block*/
00079 
00080 
00081 /*
00082  * A macro definition for allocating a new entry of DE, DL, or PNDE.  To
00083  * release such an entry, use definition release_entry (see below).
00084  *
00085  * new_entry(NEW_ENTRY,            -- pointer to the new entry
00086  *           RELEASED,             -- pointer to the released entries
00087  *           NEXT_FREE,            -- pointer to the next free entry
00088  *           CURRENT_BLOCK,        -- pointer to the current block
00089  *           CURRENT_BLOCK_TOP,    -- pointer to the current block top
00090  *           NEXT_FUNCTION,        -- next function (eg. de_next)
00091  *           ENTRY_TYPE,           -- type of the entry (eg. DE)
00092  *           BLOCK_SIZE,           -- block size (for malloc a new block)
00093  *           ABORT_MESG)           -- xsb_abort mesg when no enough memory
00094  */
00095 
00096 #define new_entry(NEW_ENTRY,                                            \
00097                   RELEASED,                                             \
00098                   NEXT_FREE,                                            \
00099                   CURRENT_BLOCK,                                        \
00100                   CURRENT_BLOCK_TOP,                                    \
00101                   NEXT_FUNCTION,                                        \
00102                   ENTRY_TYPE,                                           \
00103                   BLOCK_SIZE,                                           \
00104                   ABORT_MESG)                                           \
00105   if (RELEASED) {                                                       \
00106     NEW_ENTRY = RELEASED;                                               \
00107     RELEASED = NEXT_FUNCTION(RELEASED);                                 \
00108   }                                                                     \
00109   else if (NEXT_FREE < CURRENT_BLOCK_TOP)                               \
00110     NEW_ENTRY = NEXT_FREE++;                                            \
00111   else {                                                                \
00112     char *new_block;                                                    \
00113     if ((new_block = (char *) mem_alloc(BLOCK_SIZE + sizeof(Cell),TABLE_SPACE)) == NULL)\
00114       xsb_abort(ABORT_MESG);                                            \
00115     *(char **) new_block = CURRENT_BLOCK;                               \
00116     CURRENT_BLOCK = new_block;                                          \
00117     NEXT_FREE = (ENTRY_TYPE)(new_block + sizeof(Cell));                 \
00118     CURRENT_BLOCK_TOP = (ENTRY_TYPE)(new_block + sizeof(Cell) + BLOCK_SIZE);\
00119     NEW_ENTRY = NEXT_FREE++;                                            \
00120   }
00121 
00122 #define release_entry(ENTRY_TO_BE_RELEASED,                             \
00123                       RELEASED,                                         \
00124                       NEXT_FUNCTION) {                                  \
00125   NEXT_FUNCTION(ENTRY_TO_BE_RELEASED) = RELEASED;                       \
00126   RELEASED = ENTRY_TO_BE_RELEASED;                                      \
00127 }
00128 
00129 /*
00130  * remove_pnde(PNDE_HEAD, PNDE_ITEM) removes PNDE_ITEM from the
00131  * corresponding doubly-linked PNDE list.  If PNDE_ITEM is the first one
00132  * in the list, resets PNDE_HEAD to point to the next one.
00133  *
00134  * One principle: Whenever we remove a DE, its PDE (or NDE) must be
00135  * removed from the PNDE list *first* using remove_pnde().
00136  */
00137 
00138 #define remove_pnde(PNDE_HEAD, PNDE_ITEM) {             \
00139   PNDE *pnde_head_ptr;                                  \
00140   PNDE next;                                            \
00141                                                         \
00142   pnde_head_ptr = &(PNDE_HEAD);                         \
00143   next = pnde_next(PNDE_ITEM);                          \
00144   if (*pnde_head_ptr == PNDE_ITEM)                      \
00145     *pnde_head_ptr = next;                              \
00146   else {                                                \
00147     pnde_next(pnde_prev(PNDE_ITEM)) = next;             \
00148     if (next)                                           \
00149       pnde_prev(next) = pnde_prev(PNDE_ITEM);           \
00150   }                                                     \
00151   release_entry(PNDE_ITEM, released_pndes_gl, pnde_next);       \
00152 }
00153 
00154 /*
00155  * The following functions are used for statistics.  If changing their
00156  * usage pattern, make sure you adjust the mutexes.  (MUTEX_DELAY is
00157  * non-recursive.)   Use of NOERROR mutexes is ok here.
00158  */
00159 
00160 unsigned long allocated_de_space(int * num_blocks)
00161 {
00162   int size = 0;
00163   char *t = current_de_block_gl;
00164 
00165   *num_blocks = 0;
00166   SYS_MUTEX_LOCK_NOERROR( MUTEX_DELAY ) ;
00167   while (t) {
00168     (*num_blocks)++;
00169     size =+ (de_block_size_glc + sizeof(Cell));
00170     t = *(char **)t;
00171   }
00172   SYS_MUTEX_UNLOCK_NOERROR( MUTEX_DELAY ) ;
00173   return size;
00174 }
00175 
00176 static int released_de_num(void)
00177 {
00178   int i = 0;
00179   DE p;
00180 
00181   p = released_des_gl;
00182   SYS_MUTEX_LOCK_NOERROR( MUTEX_DELAY ) ;
00183   while (p != NULL) {
00184     i++;
00185     p = de_next(p);
00186   }
00187   SYS_MUTEX_UNLOCK_NOERROR( MUTEX_DELAY ) ;
00188   return(i);
00189 }
00190 
00191 unsigned long unused_de_space(void)
00192 {
00193   return (current_de_block_top_gl
00194           - next_free_de_gl
00195           + released_de_num()) * sizeof(struct delay_element);
00196 }
00197 
00198 
00199 unsigned long allocated_dl_space(int * num_blocks)
00200 {
00201   int size = 0;
00202   char *t = current_dl_block_gl;
00203 
00204   *num_blocks = 0;
00205   SYS_MUTEX_LOCK_NOERROR( MUTEX_DELAY ) ;
00206   while (t) {
00207     (*num_blocks)++;
00208     size =+ (dl_block_size_glc + sizeof(Cell));
00209     t = *(char **)t;
00210   }
00211   SYS_MUTEX_UNLOCK_NOERROR( MUTEX_DELAY ) ;
00212   return size;
00213 }
00214 
00215 static int released_dl_num(void)
00216 {
00217   int i = 0;
00218   DL p;
00219 
00220   p = released_dls_gl;
00221   SYS_MUTEX_LOCK_NOERROR( MUTEX_DELAY ) ;
00222   while (p != NULL) {
00223     i++;
00224     p = dl_next(p);
00225   }
00226   SYS_MUTEX_UNLOCK_NOERROR( MUTEX_DELAY ) ;
00227   return(i);
00228 }
00229 
00230 unsigned long unused_dl_space(void)
00231 {
00232   return (current_dl_block_top_gl
00233           - next_free_dl_gl
00234           + released_dl_num()) * sizeof(struct delay_list);
00235 }
00236 
00237 /*
00238  * Assign one entry for delay_elem in the current DE (Delay Element)
00239  * block.  A new block will be allocate if necessary.
00240  */
00241   
00242 static DE intern_delay_element(CTXTdeclc Cell delay_elem)
00243 {
00244   DE de;
00245   CPtr cptr = (CPtr) cs_val(delay_elem);
00246   /*
00247    * All the following information about delay_elem is set in
00248    * delay_negatively() or delay_positively().  Note that cell(cptr) is
00249    * the delay_psc ('DL').
00250    */
00251   VariantSF subgoal;
00252   NODEptr ans_subst;
00253   CPtr ret_n = 0;
00254   int arity;
00255   Cell tmp_cell;
00256 
00257   tmp_cell = cell(cptr + 1);
00258   subgoal = (VariantSF) addr_val(tmp_cell);
00259   tmp_cell = cell(cptr + 2);
00260   ans_subst = (NODEptr) addr_val(tmp_cell);
00261   tmp_cell = cell(cptr + 3);
00262   
00263   /*
00264    * cell(cptr + 3) can be one of the following:
00265    *   1. integer 0 (NEG_DELAY), for a negative DE;
00266    *   2. string "ret", for a positive DE with arity 0;
00267    *   3. constr ret/n, for a positive DE with arity >=1.
00268    */
00269   if (isinteger(tmp_cell) || isstring(tmp_cell))
00270     arity = 0;
00271   else {
00272     ret_n = (CPtr) cs_val(tmp_cell);
00273     arity = get_arity((Psc) get_str_psc(cell(cptr + 3)));
00274   }
00275 
00276 #ifdef DEBUG_DELAYVAR
00277   xsb_dbgmsg((LOG_DEBUG,">>>> "));
00278   dbg_print_delay_list(LOG_DEBUG,stddbg, delayreg);
00279   xsb_dbgmsg((LOG_DEBUG, "\n"));
00280   xsb_dbgmsg((LOG_DEBUG, ">>>> (Intern ONE de) arity of answer subsf = %d\n", 
00281              arity));
00282 #endif
00283 
00284   if (!was_simplifiable(subgoal, ans_subst)) {
00285     new_entry(de,
00286               released_des_gl,
00287               next_free_de_gl,
00288               current_de_block_gl,
00289               current_de_block_top_gl,
00290               de_next,
00291               DE,
00292               de_block_size_glc,
00293               "Not enough memory to expand DE space");
00294     de_subgoal(de) = subgoal;
00295     de_ans_subst(de) = ans_subst; /* Leaf of the answer (substitution) trie */
00296 
00297 #ifdef DEBUG_DELAYVAR
00298     de_subs_fact(de) = NULL;
00299 #ifndef IGNORE_DELAYVAR
00300     if (arity != 0) {
00301       de_subs_fact_leaf(de) = delay_chk_insert(arity, ret_n + 1,
00302                                                (CPtr *) &de_subs_fact(de));
00303     }
00304 #endif /* IGNORE_DELAYVAR */
00305 #else
00306 #ifndef IGNORE_DELAYVAR
00307     if (arity != 0) {
00308       CPtr hook = NULL;
00309       de_subs_fact_leaf(de) = delay_chk_insert(CTXTc arity, ret_n + 1,
00310                                                &hook);
00311     }
00312 #endif /* IGNORE_DELAYVAR */
00313 #endif
00314     return de;
00315   }
00316   else
00317     return NULL;
00318 }
00319 
00320 /*
00321  * Construct a delay list according to dlist.  Assign an entry in the
00322  * current DL block for it.  A new DL block will be allocated if
00323  * necessary.
00324  */
00325 
00326 static DL intern_delay_list(CTXTdeclc CPtr dlist) /* assumes that dlist != NULL */
00327 {
00328   DE head = NULL, de;
00329   DL dl = NULL;
00330 
00331   while (islist(dlist)) {
00332     dlist = clref_val(dlist);
00333     if ((de = intern_delay_element(CTXTc cell(dlist))) != NULL) {
00334       de_next(de) = head;
00335       head = de;
00336     }
00337     dlist = (CPtr) cell(dlist+1);
00338   }
00339   if (head) {
00340     new_entry(dl,
00341               released_dls_gl,
00342               next_free_dl_gl,
00343               current_dl_block_gl,
00344               current_dl_block_top_gl,
00345               dl_next,
00346               DL,
00347               dl_block_size_glc,
00348               "Not enough memory to expand DL space");
00349     dl_de_list(dl) = head;
00350     dl_asl(dl) = NULL;
00351     return dl;
00352   }
00353   else return NULL;
00354 }
00355 
00356 /*
00357  * For each delay element de in delay list dl, do one of the following
00358  * things:
00359  *
00360  * 1) (If de is a negative DE) Add a NDE `pnde' to the nde_list of de's
00361  *    subgoal frame.  Point de_pnde(de) to `pnde', and point
00362  *    pnde_dl(pnde) to dl, pnde_de(pnde) to de.
00363  *    
00364  * 2) (If de is a positive DE) Add a PDE `pnde' to the pdes of the
00365  *    Delay Info node of de's answer substitution leaf.  Point
00366  *    de_pnde(de) to `pnde', and point pnde_dl(pnde) to dl, pnde_de(pnde)
00367  *    to de.
00368  */
00369 
00370 static void record_de_usage(DL dl)
00371 {
00372   DE de;
00373   PNDE pnde, current_first;
00374   NODEptr as_leaf;
00375 #ifdef DEBUG_DELAYVAR
00376   PNDE tmp;
00377 #endif
00378  
00379   de = dl_de_list(dl);
00380   while (de) {
00381     new_entry(pnde,
00382               released_pndes_gl,
00383               next_free_pnde_gl,
00384               current_pnde_block_gl,
00385               current_pnde_block_top_gl,
00386               pnde_next,
00387               PNDE,
00388               pnde_block_size_glc,
00389               "Not enough memory to expand PNDE space");
00390     pnde_dl(pnde) = dl;
00391     pnde_de(pnde) = de;
00392     pnde_prev(pnde) = NULL;
00393     if ((as_leaf = de_ans_subst(de)) == NULL) { /* a negative DE */
00394       current_first = subg_nde_list(de_subgoal(de));
00395 #ifdef DEBUG_DELAYVAR
00396       tmp = current_first;
00397       while (tmp) {
00398         if (pnde_de(tmp) == de) {
00399           printf(">>>> ERROR: tmp = %p, tmp->de = %p\n",
00400                  tmp, pnde_de(tmp));
00401         }
00402         tmp = pnde_next(tmp);
00403       }
00404 #endif      
00405       pnde_next(pnde) = current_first;
00406       if (current_first)
00407         pnde_prev(current_first) = pnde;
00408       subg_nde_list(de_subgoal(de)) = pnde;
00409     }
00410     else {                                      /* a positive DE */
00411       current_first = asi_pdes(Delay(as_leaf));
00412       pnde_next(pnde) = current_first;
00413       if (current_first)
00414         pnde_prev(current_first) = pnde;
00415       asi_pdes(Delay(as_leaf)) = pnde;
00416     }
00417     de_pnde(de) = pnde; /* record */
00418     de = de_next(de);
00419   }
00420 }
00421 
00422 /*
00423  * For predicates using call variance, do_delay_stuff() is called in
00424  * table_answer_search(), immediately after variant_answer_search(),
00425  * regardless of whether the answer is new (conditional answer
00426  * handling is not implemented for predicates using call subsumption),
00427  * Here, `as_leaf' is the leaf node of the answer trie (the
00428  * return value of variant_answer_search), `subgoal' is the subgoal
00429  * frame of the current call, and `sf_exists' tells whether the
00430  * non-conditional part of this answer is new or not. 
00431  *
00432  * At call time, `delayreg' is the delay register of the _current_
00433  * execution state.  If delayreg is not NULL, then it means this
00434  * answer has some delay elements and is conditional.  (If non-NULL,
00435  * delayreg points to a delay list of delay elements on the heap).
00436  * This function assumes that conditional answers have previously been
00437  * checked to ensure none of their delay elements is non-satisfiable
00438  * (done in new_answer_dealloc).  At the same time, do_delay_stuff()
00439  * will recheck the delay elements to remove any that have become
00440  * unconditional.  Thus, two traversals of the delay list are
00441  * required.
00442  *
00443  * Function intern_delay_list() will be called to save the delay list
00444  * information in the Delay Info node of current call's answer leaf.  It
00445  * will call intern_delay_element(), which will call delay_chk_insert().
00446  * A delay trie is created by delay_chk_insert() for the corresponding
00447  * delay element.
00448  *
00449  * When the delay trie has been created, and a pointer in the delay
00450  * element (saved in the answer trie) has been set, we can say the
00451  * conditional answer is now tabled.
00452  * 
00453  * TLS: moved mutexes into conditionals.  This avoids locking the
00454  * delay mutex when adding an answer for a LRD stratified program.
00455  * For non-LRD programs the placement of mutexes may mean that we lock
00456  * the mutex more than once per answer, but such cases will be
00457  * uncommon for the most part (as two of the cases engender
00458  * simplification).  And in any case, if we optimize non-LRD programs
00459  * for MT, we'd probably want to deal with shared and non-shared DL/DE
00460  * alloction along the lines of structure managers.  Finally, I'm not
00461  * completely sure that simplification requires a mutex -- I need to
00462  * figure this out.
00463  */
00464 
00465 void do_delay_stuff(CTXTdeclc NODEptr as_leaf, VariantSF subgoal, xsbBool sf_exists)
00466 {
00467     ASI asi;
00468     DL dl = NULL;
00469 
00470 #ifdef DEBUG_DELAYVAR
00471     xsb_dbgmsg((LOG_DEBUG, ">>>> Start do_delay_stuff ...\n"));
00472     xsb_dbgmsg((LOG_DEBUG, ">>>> The delay list for this subgoal itself is:\n"));
00473     xsb_dbgmsg((LOG_DEBUG, ">>>> ")); 
00474     dbg_print_delay_list(LOG_DEBUG,stddbg, delayreg);
00475     xsb_dbgmsg((LOG_DEBUG, "\n"));
00476 #endif
00477 
00478     if (delayreg && (!sf_exists || is_conditional_answer(as_leaf))) {
00479       if ((dl = intern_delay_list(CTXTc delayreg)) != NULL) {
00480         SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00481         mark_conditional_answer(as_leaf, subgoal, dl);
00482         record_de_usage(dl);
00483         SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00484       }
00485     }
00486     /*
00487      * Check for the derivation of an unconditional answer.
00488      */
00489     if (sf_exists && is_conditional_answer(as_leaf) &&
00490         (!delayreg || !dl)) {
00491       /*
00492        * Initiate positive simplification in places where this answer
00493        * substitution has already been returned.
00494        */
00495       SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00496       simplify_pos_unconditional(CTXTc as_leaf);
00497       SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00498     }
00499     if (is_unconditional_answer(as_leaf) && subg_nde_list(subgoal)) {
00500       SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00501       simplify_neg_succeeds(CTXTc subgoal);
00502       SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00503     }
00504 }
00505 
00506 /*----------------------------------------------------------------------*/
00507 
00508 xsbBool answer_is_junk(CPtr dlist)        /* assumes that dlist != NULL */
00509 {
00510     CPtr    cptr;
00511     VariantSF subgoal;
00512     NODEptr ans_subst;
00513     Cell tmp_cell;
00514 
00515     while (islist(dlist)) {
00516       dlist = clref_val(dlist);
00517       cptr = (CPtr) cs_val(cell(dlist));
00518       tmp_cell = cell(cptr + 1);
00519       subgoal = (VariantSF) addr_val(tmp_cell);
00520       tmp_cell = cell(cptr + 2);
00521       ans_subst = (NODEptr) addr_val(tmp_cell);
00522       if (is_failing_delay_element(subgoal,ans_subst)) {
00523         return TRUE;
00524       }
00525       dlist = (CPtr) cell(dlist+1);
00526     }
00527     return FALSE;
00528 }
00529 
00530 /*
00531  * Function remove_de_from_dl(de, dl) removes de from dl when de is
00532  * positive and succeeds, or negative and fails.  It is used in
00533  * simplify_pos_unconditional() and simplify_neg_fails().
00534  */
00535 
00536 static xsbBool remove_de_from_dl(DE de, DL dl)
00537 {
00538   DE current = dl_de_list(dl);
00539   DE prev_de = NULL;
00540 
00541 #ifdef DEBUG_DELAYVAR
00542   fprintf(stddbg, ">>>> start remove_de_from_dl()\n");
00543 #endif
00544 
00545   while (current != de) {
00546     prev_de = current;
00547     current = de_next(current);
00548   }
00549   if (prev_de == NULL)          /* to remove the first DE */
00550     dl_de_list(dl) = de_next(current);
00551   else
00552     de_next(prev_de) = de_next(current);
00553   release_entry(current, released_des_gl, de_next);
00554   return (NULL != dl_de_list(dl));
00555 }
00556 
00557 /*
00558  * Function remove_dl_from_dl_list(dl, asi) removes dl from the DL list
00559  * which is pointed by asi.  Called when a DE in dl is negative and
00560  * succeeds, or positive and unsupported (in functions
00561  * simplify_neg_succeeds() and simplify_pos_unsupported()).
00562  */
00563 
00564 static xsbBool remove_dl_from_dl_list(DL dl, ASI asi)
00565 {
00566   DL current = asi_dl_list(asi);
00567   DL prev_dl = NULL;
00568 
00569 #ifdef DEBUG_DELAYVAR
00570   fprintf(stddbg, ">>>> start remove_dl_from_dl_list()\n");
00571 #endif
00572 
00573   while (current != dl) {
00574     prev_dl = current;
00575     current = dl_next(current);
00576   }
00577   if (prev_dl == NULL)          /* to remove the first DL */
00578     asi_dl_list(asi) = dl_next(current);
00579   else
00580     dl_next(prev_dl) = dl_next(current);
00581 
00582   release_entry(current, released_dls_gl, dl_next);
00583   return (NULL != asi_dl_list(asi));
00584 }
00585 
00586 /*
00587  * When a DL becomes empty (after remove_de_from_dl()), the answer
00588  * substitution which uses this DL becomes unconditional.  Further
00589  * simplification operations go on ...
00590  */
00591 
00592 static void handle_empty_dl_creation(CTXTdeclc DL dl)
00593 {
00594   NODEptr as_leaf = dl_asl(dl);
00595   ASI asi = Delay(as_leaf);
00596   VariantSF subgoal;
00597 
00598 #ifdef DEBUG_DELAYVAR
00599   fprintf(stddbg, ">>>> start handle_empty_dl_creation()\n");
00600 #endif
00601   /*
00602    * Only when `as_leaf' is still a conditional answer can we do
00603    * remove_dl_from_dl_list(), simplify_pos_unconditional(), and
00604    * simplify_neg_succeeds() here.
00605    *
00606    * If `as_leaf' is already marked UNCONDITIONAL (by
00607    * unmark_conditional_answer(as_leaf) in simplify_pos_unconditional()),
00608    * that means this is the second time when `as_leaf' becomes
00609    * unconditional. So we don't need do anything.  All the DLs have been
00610    * released in the first time.
00611    */
00612   if (is_conditional_answer(as_leaf)) { /* if it is still conditional */
00613     remove_dl_from_dl_list(dl, asi);
00614     subgoal = asi_subgoal(Delay(as_leaf));
00615 #ifdef DEBUG_DELAYVAR
00616     xsb_dbgmsg((LOG_DEBUG, ">>>> the subgoal is:"));
00617     dbg_print_subgoal(LOG_DEBUG,stddbg, subgoal); 
00618     xsb_dbgmsg((LOG_DEBUG, "\n"));
00619 #endif
00620     /*
00621      * simplify_pos_unconditional(as_leaf) will release all other DLs for
00622      * as_leaf, and mark as_leaf as UNCONDITIONAL.
00623      */
00624     simplify_pos_unconditional(CTXTc as_leaf);
00625     /*-- perform early completion if necessary; please preserve invariants --*/
00626     if (!is_completed(subgoal) && most_general_answer(as_leaf)) {
00627       perform_early_completion(subgoal, subg_cp_ptr(subgoal));
00628       subg_compl_susp_ptr(subgoal) = NULL;
00629     }
00630     simplify_neg_succeeds(CTXTc subgoal);
00631   }
00632 }
00633 
00634 /*
00635  * Run further simplifications when an answer substitution leaf,
00636  * as_leaf, has no supported conditional answers.  This happens when
00637  * all DLs of as_leaf are removed (by remove_dl_from_dl_list)
00638  */
00639 
00640 static void handle_unsupported_answer_subst(CTXTdeclc NODEptr as_leaf)
00641 {
00642   ASI unsup_asi = Delay(as_leaf);
00643   VariantSF unsup_subgoal = asi_subgoal(unsup_asi);
00644 
00645 #ifdef DEBUG_DELAYVAR
00646   fprintf(stddbg, ">>>> start handle_unsupported_answer_subst()\n");
00647 #endif
00648 
00649   SET_TRIE_ALLOCATION_TYPE_SF(unsup_subgoal);
00650   delete_branch(CTXTc as_leaf, &subg_ans_root_ptr(unsup_subgoal));
00651   simplify_pos_unsupported(CTXTc as_leaf);
00652   if (is_completed(unsup_subgoal)) {
00653     if (subgoal_fails(unsup_subgoal)) {
00654       simplify_neg_fails(CTXTc unsup_subgoal);
00655     }
00656   }
00657   mem_dealloc(unsup_asi,sizeof(struct AS_info),TABLE_SPACE);
00658 }
00659 
00660 /*
00661  * To release all the DLs (and their DEs) in the DelayInfo node `asi'.
00662  */
00663 
00664 void release_all_dls(ASI asi)
00665 {
00666   ASI de_asi;
00667   DE de, tmp_de;
00668   DL dl, tmp_dl;
00669 
00670   dl = asi_dl_list(asi);
00671   while (dl) {
00672     tmp_dl = dl_next(dl);
00673     de = dl_de_list(dl);
00674     while (de) {
00675       tmp_de = de_next(de);
00676       if (de_ans_subst(de) == NULL) { /* is NDE */
00677         remove_pnde(subg_nde_list(de_subgoal(de)), de_pnde(de));
00678       }
00679       else {
00680         de_asi = Delay(de_ans_subst(de));
00681         remove_pnde(asi_pdes(de_asi), de_pnde(de));
00682       }
00683       release_entry(de, released_des_gl, de_next);
00684       de = tmp_de; /* next DE */
00685     } /* while (de) */
00686     release_entry(dl, released_dls_gl, dl_next);
00687     dl = tmp_dl; /* next DL */
00688   }
00689 }
00690 
00691 /*
00692  * When the answers substitution gets an unconditional answer, remove
00693  * the positive delay literals of this answer substitution from the
00694  * delay lists that contain them.
00695  */
00696 
00697 static void simplify_pos_unconditional(CTXTdeclc NODEptr as_leaf)
00698 {
00699   ASI asi = Delay(as_leaf);
00700   PNDE pde;
00701   DE de;
00702   DL dl;
00703 
00704 #ifdef DEBUG_DELAYVAR
00705   fprintf(stddbg, ">>>> start simplify_pos_unconditional()\n");
00706 #endif
00707 
00708   release_all_dls(asi);
00709   
00710   unmark_conditional_answer(as_leaf);
00711 
00712   while ((pde = asi_pdes(asi))) {
00713     de = pnde_de(pde);
00714     dl = pnde_dl(pde);
00715     remove_pnde(asi_pdes(asi), pde);
00716     if (!remove_de_from_dl(de, dl))
00717       handle_empty_dl_creation(CTXTc dl);
00718   }
00719   /*
00720    * Now this DelayInfo `asi' does not contain any useful info, so we can
00721    * free it, and really mark `as_leaf' as an unconditional answer.
00722    */
00723   Child(as_leaf) = NULL;
00724   mem_dealloc(asi,sizeof(struct AS_info),TABLE_SPACE);
00725 }
00726 
00727 /*
00728  * When the subgoal fails (is completed without any answers), remove
00729  * the negative delay literals of this subgoal from the delay lists
00730  * that contain them.
00731  */
00732 
00733 void simplify_neg_fails(CTXTdeclc VariantSF subgoal)
00734 {
00735   PNDE nde;
00736   DE de;
00737   DL dl;
00738 
00739 #ifdef DEBUG_DELAYVAR
00740   xsb_dbgmsg((LOG_DEBUG, ">>>> start simplify_neg_fails()\n"));
00741   xsb_dbgmsg((LOG_DEBUG, ">>>> the subgoal is: "));
00742   dbg_print_subgoal(LOG_DEBUG,stddbg, subgoal); 
00743   xsb_dbgmsg((LOG_DEBUG, "\n"));
00744 #endif
00745 
00746   while ((nde = subg_nde_list(subgoal))) {
00747     de = pnde_de(nde);
00748     dl = pnde_dl(nde);
00749     remove_pnde(subg_nde_list(subgoal), nde);
00750     if (!remove_de_from_dl(de, dl))
00751       handle_empty_dl_creation(CTXTc dl);
00752   }
00753 
00754 #ifdef DEBUG_DELAYVAR
00755   fprintf(stddbg, ">>>> end simplify_neg_fails()\n");
00756 #endif
00757   
00758 }
00759 
00760 /*
00761  * On occasion that the subgoal succeeds (gets an unconditional 
00762  * answer that is identical to the subgoal), it deletes all delay       
00763  * lists that contain a negative delay element with that subgoal.
00764  * 
00765  * Before remove_dl_from_dl_list(), all the DEs in the DL to be
00766  * removed have to be released, and each P(N)DE which points to a DE
00767  * in the DL has also to be released.
00768  */
00769 
00770 static void simplify_neg_succeeds(CTXTdeclc VariantSF subgoal)
00771 {
00772   PNDE nde;
00773   DL dl;
00774   DE de, tmp_de;
00775   ASI used_asi, de_asi;
00776   NODEptr used_as_leaf;
00777 
00778 #ifdef DEBUG_DELAYVAR
00779   fprintf(stddbg, ">>>> start simplify_neg_succeeds()\n");
00780 #endif
00781 
00782   while ((nde = subg_nde_list(subgoal))) {
00783     dl = pnde_dl(nde); /* dl: to be removed */
00784     used_as_leaf = dl_asl(dl);
00785     if (IsValidNode(used_as_leaf) &&
00786         (used_asi = Delay(used_as_leaf)) != NULL) {
00787       de = dl_de_list(dl); /* to release all DEs in dl */
00788       while (de) {
00789         tmp_de = de_next(de);
00790         if (de_ans_subst(de) == NULL) { /* is NDE */
00791           remove_pnde(subg_nde_list(de_subgoal(de)), de_pnde(de));
00792         }
00793         else {
00794           de_asi = Delay(de_ans_subst(de));
00795           remove_pnde(asi_pdes(de_asi), de_pnde(de));
00796         }
00797 #ifdef DEBUG_DELAYVAR
00798         fprintf(stddbg, ">>>> release DE (in simplify_neg_succeeds)\n");
00799 #endif
00800         release_entry(de, released_des_gl, de_next);
00801         de = tmp_de; /* next DE */
00802       } /* while */
00803       if (!remove_dl_from_dl_list(dl, used_asi)) {
00804         handle_unsupported_answer_subst(CTXTc used_as_leaf);
00805       }
00806     } /* if */
00807   } /* while */
00808 }
00809 
00810 /*
00811  * On occasion that an AnswerSubstitution at `as_leaf' looses all its
00812  * conditional answers (all its DLs have been removed),
00813  * simplify_pos_unsupported() deletes all delay lists (of other
00814  * predicates' conditional answers) that contain a positive delay element
00815  * pointing to that AnswerSubstitution.
00816  */
00817 
00818 void simplify_pos_unsupported(CTXTdeclc NODEptr as_leaf)
00819 {
00820   ASI asi = Delay(as_leaf);
00821   PNDE pde;
00822   DL dl;
00823   DE de, tmp_de;
00824   ASI used_asi, de_asi;
00825   NODEptr used_as_leaf;
00826 
00827 #ifdef DEBUG_DELAYVAR
00828   fprintf(stddbg, ">>>> start simplify_pos_unsupported()\n");
00829 #endif
00830 
00831   while ((pde = asi_pdes(asi))) {
00832     dl = pnde_dl(pde); /* dl: to be removed */
00833     used_as_leaf = dl_asl(dl);
00834     if (IsValidNode(used_as_leaf) &&
00835         (used_asi = Delay(used_as_leaf)) != NULL) {
00836       de = dl_de_list(dl); /* to release all DEs in dl */
00837       while (de) {
00838         tmp_de = de_next(de);
00839         if (de_ans_subst(de) == NULL) { /* is NDE */
00840           remove_pnde(subg_nde_list(de_subgoal(de)), de_pnde(de));
00841         }
00842         else {                    /* is PDE */
00843           de_asi = Delay(de_ans_subst(de));
00844           remove_pnde(asi_pdes(de_asi), de_pnde(de));
00845         }
00846 #ifdef DEBUG_DELAYVAR
00847         fprintf(stddbg, ">>>> release DE (in simplify_pos_unsupported)");
00848 #endif
00849         release_entry(de, released_des_gl, de_next);
00850         de = tmp_de; /* next DE */
00851       } /* while */
00852       if (!remove_dl_from_dl_list(dl, used_asi)) {
00853         handle_unsupported_answer_subst(CTXTc used_as_leaf);
00854       }
00855     } /* if */
00856   } /* while */
00857 }
00858 
00859 /* Can currently be called with only one active thread: otherwise put
00860    mutexes back in. */
00861 void abolish_wfs_space(CTXTdecl)
00862 {
00863   char *last_block;
00864 
00865 #ifndef LOCAL_EVAL
00866     extern void abolish_edge_space();
00867 #endif
00868 
00869   /* clear DE blocks */
00870 
00871     //    SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00872   while (current_de_block_gl) {
00873     last_block = *(char **) current_de_block_gl;
00874     mem_dealloc(current_de_block_gl,de_block_size_glc + sizeof(Cell),TABLE_SPACE);
00875     current_de_block_gl = last_block;
00876   }
00877 
00878   /* clear DL blocks */
00879 
00880   while (current_dl_block_gl) {
00881     last_block = *(char **) current_dl_block_gl;
00882     mem_dealloc(current_dl_block_gl,dl_block_size_glc + sizeof(Cell),TABLE_SPACE);
00883     current_dl_block_gl = last_block;
00884   }
00885 
00886   /* clear PNDE blocks */
00887   
00888   while (current_pnde_block_gl) {
00889     last_block = *(char **) current_pnde_block_gl;
00890     mem_dealloc(current_pnde_block_gl,pnde_block_size_glc + sizeof(Cell),TABLE_SPACE);
00891     current_pnde_block_gl = last_block;
00892   }
00893 
00894   /* reset some pointers */
00895   
00896   released_des_gl = NULL;
00897   released_dls_gl = NULL;
00898   released_pndes_gl = NULL;
00899 
00900   next_free_de_gl = NULL;
00901   next_free_dl_gl = NULL;
00902   next_free_pnde_gl = NULL;
00903 
00904   current_de_block_top_gl = NULL;
00905   current_dl_block_top_gl = NULL;
00906   current_pnde_block_top_gl = NULL;
00907 
00908 #ifndef LOCAL_EVAL
00909     abolish_edge_space();
00910 #endif
00911     //    SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00912 }
00913 
00914 /*
00915  * Two functions added for builtin force_truth_value/2.
00916  */
00917 
00918 void force_answer_true(CTXTdeclc NODEptr as_leaf)
00919 {
00920   VariantSF subgoal;
00921   
00922   if (is_conditional_answer(as_leaf)) {
00923     SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00924     subgoal = asi_subgoal(Delay(as_leaf));
00925     simplify_pos_unconditional(CTXTc as_leaf);
00926     simplify_neg_succeeds(CTXTc subgoal);
00927     SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00928   }
00929 }
00930 
00931 void force_answer_false(CTXTdeclc NODEptr as_leaf)
00932 {
00933   ASI asi = Delay(as_leaf);
00934   VariantSF subgoal;
00935 
00936   if (is_conditional_answer(as_leaf)) {
00937     SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00938     subgoal = asi_subgoal(asi);
00939     release_all_dls(asi);
00940     SET_TRIE_ALLOCATION_TYPE_SF(subgoal);
00941     delete_branch(CTXTc as_leaf, &subg_ans_root_ptr(subgoal));
00942     simplify_pos_unsupported(CTXTc as_leaf);
00943     mark_subgoal_failed(subgoal);
00944     simplify_neg_fails(CTXTc subgoal);
00945     SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00946   }
00947 }
00948 
00949 /*---------------------- end of file slgdelay.c ------------------------*/

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