macro_xsb.h

00001 /* File:      macro_xsb.h
00002 ** Author(s): Swift, Sagonas, Rao, Freire, Johnson
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** 
00007 ** XSB is free software; you can redistribute it and/or modify it under the
00008 ** terms of the GNU Library General Public License as published by the Free
00009 ** Software Foundation; either version 2 of the License, or (at your option)
00010 ** any later version.
00011 ** 
00012 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00013 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00015 ** more details.
00016 ** 
00017 ** You should have received a copy of the GNU Library General Public License
00018 ** along with XSB; if not, write to the Free Software Foundation,
00019 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 **
00021 ** $Id: macro_xsb.h,v 1.48 2006/07/04 01:28:18 tswift Exp $
00022 ** 
00023 */
00024 
00025 #ifndef __MACRO_XSB_H__
00026 #define __MACRO_XSB_H__
00027 
00028 #include "debug_xsb.h"
00029 
00030 /*----------------------------------------------------------------------*/
00031 
00032 /* typedef struct subgoal_frame *VariantSF; */
00033 
00034 /*===========================================================================*/
00035 
00036 /*             
00037  *                   Deleted Table Frame Records
00038  *                   ===========================
00039  *
00040  *    These records are used to hold pointers to abolished call and
00041  *    answer tries for table garbage collection.  These are effective
00042  *    a union type, as they can hold deleted subgoals as well as
00043  *    deleted predicates.
00044  */     
00045 
00046 typedef struct Deleted_Table_Frame *DelTFptr;
00047 typedef struct Deleted_Table_Frame {
00048   BTNptr call_trie;             /* pointer to the root of the call trie */
00049   VariantSF subgoals;           /* chain of predicate's subgoals */
00050   byte      type;                /* Marked by scan of CP stack */
00051   byte      mark;                /* Marked by scan of CP stack */
00052   DelTFptr next_delTF;          /* pointer to next table info frame */
00053   DelTFptr next_pred_delTF;     /* pointer to next table info frame same pred */
00054   DelTFptr prev_delTF;          /* pointer to prev table info frame */
00055   DelTFptr prev_pred_delTF;     /* pointer to prev table info frame same pred */
00056 } DeletedTableFrame;
00057 
00058 #define DELETED_PREDICATE 0 
00059 #define DELETED_SUBGOAL 1
00060 
00061 #define DTF_Mark(pDTF)             ( (pDTF)->mark )
00062 #define DTF_Type(pDTF)             ( (pDTF)->type )
00063 #define DTF_CallTrie(pDTF)         ( (pDTF)->call_trie )
00064 #define DTF_Subgoals(pDTF)         ( (pDTF)->subgoals )
00065 #define DTF_Subgoal(pDTF)          ( (pDTF)->subgoals )
00066 #define DTF_NextDTF(pDTF)          ( (pDTF)->next_delTF )
00067 #define DTF_NextPredDTF(pDTF)      ( (pDTF)->next_pred_delTF )
00068 #define DTF_PrevDTF(pDTF)          ( (pDTF)->prev_delTF )
00069 #define DTF_PrevPredDTF(pDTF)      ( (pDTF)->prev_pred_delTF )
00070 
00071 /* Creating two doubly-linked chains -- one for all DelTf, the other
00072    for Deltfs for this predicate.  */
00073 #define New_Global_DelTF_Pred(pDTF,pTIF) {                              \
00074    pDTF = (DelTFptr)mem_alloc(sizeof(DeletedTableFrame),TABLE_SPACE);   \
00075    if ( IsNULL(pDTF) )                                                  \
00076      xsb_abort("Ran out of memory in allocation of DeletedTableFrame"); \
00077    DTF_CallTrie(pDTF) = TIF_CallTrie(pTIF);                             \
00078    DTF_Subgoals(pDTF) = TIF_Subgoals(pTIF);                             \
00079    DTF_Type(pDTF) = DELETED_PREDICATE;                                  \
00080    DTF_Mark(pDTF) = 0;                                                  \
00081    DTF_PrevDTF(pDTF) = 0;                                               \
00082    DTF_PrevPredDTF(pDTF) = 0;                                           \
00083    DTF_NextDTF(pDTF) = deltf_chain_begin;                               \
00084    DTF_NextPredDTF(pDTF) = TIF_DelTF(pTIF);                             \
00085    if (deltf_chain_begin) DTF_PrevDTF(deltf_chain_begin) = pDTF;        \
00086    if (TIF_DelTF(pTIF))  DTF_PrevPredDTF(TIF_DelTF(pTIF)) = pDTF;       \
00087    deltf_chain_begin = pDTF;                                            \
00088    TIF_DelTF(pTIF) = pDTF;                                              \
00089   }
00090 
00091 /* Creating two doubly-linked chains -- one for all DelTf, the other
00092    for Deltfs for this predicate -- this may not be necess for
00093    _subgoal */
00094 #define New_Global_DelTF_Subgoal(pDTF,pTIF,pSubgoal) {                  \
00095    pDTF = (DelTFptr)mem_alloc(sizeof(DeletedTableFrame),TABLE_SPACE);   \
00096    if ( IsNULL(pDTF) )                                                  \
00097      xsb_abort("Ran out of memory in allocation of DeletedTableFrame"); \
00098    DTF_CallTrie(pDTF) = NULL;                                           \
00099    DTF_Subgoal(pDTF) = pSubgoal;                                        \
00100    DTF_Type(pDTF) = DELETED_SUBGOAL;                                            \
00101    DTF_Mark(pDTF) = 0;                                                  \
00102    DTF_PrevDTF(pDTF) = 0;                                               \
00103    DTF_PrevPredDTF(pDTF) = 0;                                           \
00104    DTF_NextDTF(pDTF) = deltf_chain_begin;                               \
00105    DTF_NextPredDTF(pDTF) = TIF_DelTF(pTIF);                             \
00106    if (deltf_chain_begin) DTF_PrevDTF(deltf_chain_begin) = pDTF;        \
00107    if (TIF_DelTF(pTIF))  DTF_PrevPredDTF(TIF_DelTF(pTIF)) = pDTF;       \
00108    deltf_chain_begin = pDTF;                                            \
00109    TIF_DelTF(pTIF) = pDTF;                                              \
00110   }
00111 
00112 /* In macro below, need to reset DTF chain, and Pred-level DTF chain.
00113  * No mutexes, because it is called only during gc, w. only 1 active
00114  * thread. */
00115 #define Free_Global_DelTF_Pred(pDTF,pTIF) {                             \
00116   if (DTF_PrevDTF(pDTF) == 0) {                                         \
00117     deltf_chain_begin = DTF_NextDTF(pDTF);                              \
00118   }                                                                     \
00119   else {                                                                \
00120     DTF_NextDTF(DTF_PrevDTF(pDTF)) = DTF_NextDTF(pDTF);                 \
00121   }                                                                     \
00122   if (DTF_NextDTF(pDTF) != 0) {                                         \
00123     DTF_PrevDTF(DTF_NextDTF(pDTF)) = DTF_PrevDTF(pDTF);                 \
00124   }                                                                     \
00125   if (DTF_PrevPredDTF(pDTF) == 0) {                                     \
00126     TIF_DelTF(pTIF) = DTF_NextDTF(pDTF);                                \
00127   }                                                                     \
00128   else {                                                                \
00129     DTF_NextPredDTF(DTF_PrevPredDTF(pDTF)) = DTF_NextPredDTF(pDTF);     \
00130   }                                                                     \
00131   if (DTF_NextPredDTF(pDTF) != 0) {                                     \
00132     DTF_PrevPredDTF(DTF_NextPredDTF(pDTF)) = DTF_PrevPredDTF(pDTF);     \
00133   }                                                                     \
00134   mem_dealloc(pDTF,sizeof(DeletedTableFrame),TABLE_SPACE);              \
00135 }
00136 
00137 #define Free_Global_DelTF_Subgoal(pDTF,pTIF) {                          \
00138   if (DTF_PrevDTF(pDTF) == 0) {                                         \
00139     deltf_chain_begin = DTF_NextDTF(pDTF);                              \
00140   }                                                                     \
00141   else {                                                                \
00142     DTF_NextDTF(DTF_PrevDTF(pDTF)) = DTF_NextDTF(pDTF);                 \
00143   }                                                                     \
00144   if (DTF_NextDTF(pDTF) != 0) {                                         \
00145     DTF_PrevDTF(DTF_NextDTF(pDTF)) = DTF_PrevDTF(pDTF);                 \
00146   }                                                                     \
00147   if (DTF_PrevPredDTF(pDTF) == 0) {                                     \
00148     TIF_DelTF(pTIF) = DTF_NextDTF(pDTF);                                \
00149   }                                                                     \
00150   if (DTF_PrevPredDTF(pDTF) != 0) {                                     \
00151     DTF_NextPredDTF(DTF_PrevPredDTF(pDTF)) = DTF_NextPredDTF(pDTF);     \
00152   }                                                                     \
00153   if (DTF_NextPredDTF(pDTF) != 0) {                                     \
00154     DTF_PrevPredDTF(DTF_NextPredDTF(pDTF)) = DTF_PrevPredDTF(pDTF);     \
00155   }                                                                     \
00156   mem_dealloc(pDTF,sizeof(DeletedTableFrame),TABLE_SPACE);              \
00157 }
00158 
00159 #ifdef MULTI_THREAD
00160 #define New_Private_DelTF_Pred(pDTF,pTIF) {                             \
00161    pDTF = (DelTFptr)mem_alloc(sizeof(DeletedTableFrame),TABLE_SPACE);   \
00162    if ( IsNULL(pDTF) )                                                  \
00163      xsb_abort("Ran out of memory in allocation of DeletedTableFrame"); \
00164    DTF_CallTrie(pDTF) = TIF_CallTrie(pTIF);                             \
00165    DTF_Subgoals(pDTF) = TIF_Subgoals(pTIF);                             \
00166    DTF_Type(pDTF) = DELETED_PREDICATE;                                  \
00167    DTF_Mark(pDTF) = 0;                                                  \
00168    DTF_PrevDTF(pDTF) = 0;                                               \
00169    DTF_PrevPredDTF(pDTF) = 0;                                           \
00170    DTF_NextDTF(pDTF) = private_deltf_chain_begin;                       \
00171    DTF_NextPredDTF(pDTF) = TIF_DelTF(pTIF);                             \
00172    if (private_deltf_chain_begin)                                       \
00173      DTF_PrevDTF(private_deltf_chain_begin) = pDTF;                     \
00174    if (TIF_DelTF(pTIF))  DTF_PrevPredDTF(TIF_DelTF(pTIF)) = pDTF;       \
00175    private_deltf_chain_begin = pDTF;                                    \
00176    TIF_DelTF(pTIF) = pDTF;                                              \
00177   }
00178 
00179 #define New_Private_DelTF_Subgoal(pDTF,pTIF,pSubgoal) {                 \
00180    pDTF = (DelTFptr)mem_alloc(sizeof(DeletedTableFrame),TABLE_SPACE);   \
00181    if ( IsNULL(pDTF) )                                                  \
00182      xsb_abort("Ran out of memory in allocation of DeletedTableFrame"); \
00183    DTF_CallTrie(pDTF) = NULL;                                           \
00184    DTF_Subgoal(pDTF) = pSubgoal;                                        \
00185    DTF_Type(pDTF) = DELETED_SUBGOAL;                                    \
00186    DTF_Mark(pDTF) = 0;                                                  \
00187    DTF_PrevDTF(pDTF) = 0;                                               \
00188    DTF_PrevPredDTF(pDTF) = 0;                                           \
00189    DTF_NextDTF(pDTF) = private_deltf_chain_begin;                       \
00190    DTF_NextPredDTF(pDTF) = TIF_DelTF(pTIF);                             \
00191    if (private_deltf_chain_begin)                                       \
00192      DTF_PrevDTF(private_deltf_chain_begin) = pDTF;                             \
00193    if (TIF_DelTF(pTIF))  DTF_PrevPredDTF(TIF_DelTF(pTIF)) = pDTF;       \
00194    private_deltf_chain_begin = pDTF;                                    \
00195    TIF_DelTF(pTIF) = pDTF;                                              \
00196   }
00197 
00198 /* In macro below, need to reset DTF chain, and Pred-level DTF chain.
00199  * No mutexes, because it is called only during gc, w. only 1 active
00200  * thread. */
00201 #define Free_Private_DelTF_Pred(pDTF,pTIF) {                            \
00202   if (DTF_PrevDTF(pDTF) == 0) {                                         \
00203     private_deltf_chain_begin = DTF_NextDTF(pDTF);                      \
00204   }                                                                     \
00205   else {                                                                \
00206     DTF_NextDTF(DTF_PrevDTF(pDTF)) = DTF_NextDTF(pDTF);                 \
00207   }                                                                     \
00208   if (DTF_NextDTF(pDTF) != 0) {                                         \
00209     DTF_PrevDTF(DTF_NextDTF(pDTF)) = DTF_PrevDTF(pDTF);                 \
00210   }                                                                     \
00211   if (DTF_PrevPredDTF(pDTF) == 0) {                                     \
00212     TIF_DelTF(pTIF) = DTF_NextDTF(pDTF);                                \
00213   }                                                                     \
00214   else {                                                                \
00215     DTF_NextPredDTF(DTF_PrevPredDTF(pDTF)) = DTF_NextPredDTF(pDTF);     \
00216   }                                                                     \
00217   if (DTF_NextPredDTF(pDTF) != 0) {                                     \
00218     DTF_PrevPredDTF(DTF_NextPredDTF(pDTF)) = DTF_PrevPredDTF(pDTF);     \
00219   }                                                                     \
00220   mem_dealloc(pDTF,sizeof(DeletedTableFrame),TABLE_SPACE);              \
00221 }
00222 
00223 #define Free_Private_DelTF_Subgoal(pDTF,pTIF) {                         \
00224   if (DTF_PrevDTF(pDTF) == 0) {                                         \
00225     private_deltf_chain_begin = DTF_NextDTF(pDTF);                              \
00226   }                                                                     \
00227   else {                                                                \
00228     DTF_NextDTF(DTF_PrevDTF(pDTF)) = DTF_NextDTF(pDTF);                 \
00229   }                                                                     \
00230   if (DTF_NextDTF(pDTF) != 0) {                                         \
00231     DTF_PrevDTF(DTF_NextDTF(pDTF)) = DTF_PrevDTF(pDTF);                 \
00232   }                                                                     \
00233   if (DTF_PrevPredDTF(pDTF) == 0) {                                     \
00234     TIF_DelTF(pTIF) = DTF_NextDTF(pDTF);                                \
00235   }                                                                     \
00236   if (DTF_PrevPredDTF(pDTF) != 0) {                                     \
00237     DTF_NextPredDTF(DTF_PrevPredDTF(pDTF)) = DTF_NextPredDTF(pDTF);     \
00238   }                                                                     \
00239   if (DTF_NextPredDTF(pDTF) != 0) {                                     \
00240     DTF_PrevPredDTF(DTF_NextPredDTF(pDTF)) = DTF_PrevPredDTF(pDTF);     \
00241   }                                                                     \
00242   mem_dealloc(pDTF,sizeof(DeletedTableFrame),TABLE_SPACE);              \
00243 }
00244 
00245 #endif
00246 
00247 /*===========================================================================*/
00248 
00249 /*             
00250  *                   Predicate Reference Records
00251  *                   ===========================
00252  *
00253  *    These records are used to hold some predicate-level information
00254  *    for dynamic code (non-trie asserted).  Prrefs are pointed to by
00255  *    the ep field of a PSC record and in turn point to ClRefs of each
00256  *    asserted clause and back to the PSC record itself.  Prrefs also
00257  *    contain fields for various GC information for the dynamic
00258  *    predicate and its clauses.
00259  */
00260 
00261 typedef struct Deleted_Clause_Frame *DelCFptr;
00262 typedef struct {
00263   Cell  Instr ;
00264   struct ClRefHdr *FirstClRef ;
00265   struct ClRefHdr *LastClRef ;
00266   Psc psc;                          // pointer to PSC
00267   int mark;                         // mark (for gc)
00268   //  int generation; 
00269   DelCFptr delcf;                      // delcf pointer
00270 }       *PrRef, PrRefData ;
00271 
00272 #define PrRef_Instr(PRREF)          ( (PRREF)->Instr )
00273 #define PrRef_FirstClRef(PRREF)     ( (PRREF)->FirstClRef )
00274 #define PrRef_LastClRef(PRREF)      ( (PRREF)->LastClRef )
00275 //#define PrRef_Generation(PRREF)     ( (PRREF)->generation )
00276 #define PrRef_Psc(PRREF)            ( (PRREF)->psc )
00277 #define PrRef_Mark(PRREF)           ( (PRREF)->mark )
00278 #define PrRef_DelCF(PRREF)          ( (PRREF)->delcf )
00279 
00280 /* Can't use CTXTdeclc here because its included early in context.h */
00281 #ifdef MULTI_THREAD
00282 extern xsbBool assert_buff_to_clref_p(struct th_context *, prolog_term, byte, 
00283                                       PrRef, int, prolog_term, int, ClRef *);
00284 
00285 extern int assert_code_to_buff_p(struct th_context *, prolog_term);
00286 #else
00287 extern xsbBool assert_buff_to_clref_p(prolog_term, byte, PrRef, int,
00288                                prolog_term, int, ClRef *);
00289 
00290 extern int assert_code_to_buff_p(prolog_term);
00291 #endif
00292 
00293 
00294 /*===========================================================================*/
00295 
00296 /*             
00297  *                   Deleted Clause Frames`
00298  *                   ===========================
00299  *
00300  *    These records are used to hold pointers to abolished dynamic
00301  *    predicates and clauses for dynamic clause garbage collection.
00302  *    These are effectively a union type, as they can hold deleted
00303  *    clauses as well as information about retractall-ed or abolished
00304  *    predicates.
00305  */     
00306 
00307 typedef struct Deleted_Clause_Frame {
00308   PrRef prref;                  /* ptr to prref whose clauses are to be deleted*/
00309   ClRef clref;                  /* ptr to first CLref in chain */
00310   //  int generation;           /* generation of retractalled prref*/
00311   Psc psc;                      /* pointer to psc of prref (necess?) */
00312   byte      type;               /* Prref or Clref */
00313   byte      mark;               /* Marked by scan of CP stack */
00314   DelCFptr next_delCF;          /* pointer to next DelCl frame */
00315   DelCFptr next_pred_delCF;     /* pointer to next DelCl frame same pred */
00316   DelCFptr prev_delCF;          /* pointer to prev DelCl frame */
00317   DelCFptr prev_pred_delCF;     /* pointer to prev DelCl frame same pred */
00318 } DeletedClauseFrame;
00319 
00320 #define DELETED_PRREF 0 
00321 #define DELETED_CLREF 1
00322 
00323 #define DCF_Mark(pDCF)             ( (pDCF)->mark )
00324 #define DCF_Type(pDCF)             ( (pDCF)->type )
00325 #define DCF_PrRef(pDCF)            ( (pDCF)->prref )
00326 #define DCF_ClRef(pDCF)            ( (pDCF)->clref )
00327 //#define DCF_Generation(pDCF)     ( (pDCF)->generation )
00328 #define DCF_PSC(pDCF)              ( (pDCF)->psc )
00329 #define DCF_NextDCF(pDCF)          ( (pDCF)->next_delCF )
00330 #define DCF_PrevDCF(pDCF)          ( (pDCF)->prev_delCF )
00331 #define DCF_NextPredDCF(pDCF)      ( (pDCF)->next_pred_delCF )
00332 #define DCF_PrevPredDCF(pDCF)      ( (pDCF)->prev_pred_delCF )
00333 
00334 /*===========================================================================*/
00335 
00336 /*
00337  *                         Table Information Frame
00338  *                         =======================
00339  *
00340  *  Table Information Frames are created for each tabled predicate,
00341  *  allowing access to its calls and their associated answers.
00342  */
00343 
00344 #include "table_status_defs.h"
00345 
00346 /*
00347  *typedef enum Tabled_Evaluation_Method {
00348  *  VARIANT_TEM      = VARIANT_EVAL_METHOD,
00349  *  SUBSUMPTIVE_TEM  = SUBSUMPTIVE_EVAL_METHOD,
00350  * DISPATCH_BLOCK    = 3
00351  *} TabledEvalMethod;
00352  */
00353 
00354 #define isSharedTIF(pTIF)   (TIF_EvalMethod(pTIF) != DISPATCH_BLOCK)
00355 #define isPrivateTIF(pTIF)  (TIF_EvalMethod(pTIF) == DISPATCH_BLOCK)
00356 
00357 typedef byte TabledEvalMethod;
00358 
00359 typedef struct Table_Info_Frame *TIFptr;
00360 typedef struct Table_Info_Frame {
00361   Psc  psc_ptr;                 /* pointer to the PSC record of the subgoal */
00362   byte method;                  /* eval pred using variant or subsumption? */
00363   byte mark;                    /* (bit) to indicate tif marked for gc */
00364   DelTFptr del_tf_ptr;          /* pointer to first deletion frame for pred */
00365   BTNptr call_trie;             /* pointer to the root of the call trie */
00366   VariantSF subgoals;           /* chain of predicate's subgoals */
00367   TIFptr next_tif;              /* pointer to next table info frame */
00368 } TableInfoFrame;
00369 
00370 #define TIF_PSC(pTIF)              ( (pTIF)->psc_ptr )
00371 #define TIF_DelTF(pTIF)            ( (pTIF)->del_tf_ptr )
00372 #define TIF_EvalMethod(pTIF)       ( (pTIF)->method )
00373 #define TIF_Mark(pTIF)             ( (pTIF)->mark )
00374 #define TIF_CallTrie(pTIF)         ( (pTIF)->call_trie )
00375 #define TIF_Subgoals(pTIF)         ( (pTIF)->subgoals )
00376 #define TIF_NextTIF(pTIF)          ( (pTIF)->next_tif )
00377 
00378 #define cps_check_mark_tif(pTIF)   TIF_Mark(pTIF) = 0x1
00379 #define cps_check_unmark_tif(pTIF)   TIF_Mark(pTIF) = 0x0
00380 
00381 /*
00382  * #define IsVariantPredicate(pTIF)             \
00383  *   ( TIF_EvalMethod(pTIF) == VARIANT_TEM )
00384  *
00385  * #define IsSubsumptivePredicate(pTIF)         \
00386  *   ( TIF_EvalMethod(pTIF) == SUBSUMPTIVE_TEM )
00387  */
00388 
00389 #define IsVariantPredicate(pTIF)                \
00390    ( TIF_EvalMethod(pTIF) == VARIANT_EVAL_METHOD )
00391 
00392 #define IsSubsumptivePredicate(pTIF)            \
00393  ( TIF_EvalMethod(pTIF) == SUBSUMPTIVE_EVAL_METHOD )
00394 
00395 struct tif_list {
00396   TIFptr first;
00397   TIFptr last;
00398 };
00399 extern struct tif_list  tif_list;
00400 
00401 /* TLS: New_TIF is now a function in tables.c */
00402 
00403 #ifdef MULTI_THREAD
00404 extern TIFptr New_TIF(struct th_context *,Psc);
00405 #else
00406 extern TIFptr New_TIF(Psc);
00407 #endif
00408 
00409 /* TLS: as of 8/05 tifs are freed only when abolishing a dynamic
00410    tabled predicate, (or when exiting a thread to abolish
00411    thread-private tables).  Otherwise, keep the TIF around. */
00412 
00413 /* shared tifs use the global structure tif_list.  Thus, the
00414    sequential engine uses Free_Shared_Tif rather than
00415    Free_Private_TIF */
00416    
00417 #define Free_Shared_TIF(pTIF) {                                         \
00418     TIFptr tTIF;                                                        \
00419     SYS_MUTEX_LOCK( MUTEX_TABLE );                                      \
00420     tTIF = tif_list.first;                                              \
00421     if (tTIF ==  (pTIF)) {                                              \
00422       tif_list.first = TIF_NextTIF((pTIF));                             \
00423       if  (tif_list.last == (pTIF)) tif_list.last = NULL;               \
00424     }                                                                   \
00425     else {                                                              \
00426       while  (tTIF != NULL && TIF_NextTIF(tTIF) != (pTIF))              \
00427         tTIF =  TIF_NextTIF(tTIF);                                      \
00428       if (!tTIF) xsb_exit("Trying to free nonexistent TIF");            \
00429       if ((pTIF) == tif_list.last) tif_list.last = tTIF;                \
00430       TIF_NextTIF(tTIF) = TIF_NextTIF((pTIF));                          \
00431     }                                                                   \
00432     SYS_MUTEX_UNLOCK( MUTEX_TABLE );                                    \
00433     delete_predicate_table(CTXTc pTIF);                                 \
00434     mem_dealloc((pTIF),sizeof(TableInfoFrame),TABLE_SPACE);             \
00435   }
00436 
00437 #define Free_Private_TIF(pTIF) {                                        \
00438     TIFptr tTIF = private_tif_list.first;                               \
00439     if (tTIF ==  (pTIF)) {                                              \
00440       private_tif_list.first = TIF_NextTIF((pTIF));                     \
00441       if  (private_tif_list.last == (pTIF)) private_tif_list.last = NULL; \
00442     }                                                                   \
00443     else {                                                              \
00444       while  (tTIF != NULL && TIF_NextTIF(tTIF) != (pTIF))              \
00445         tTIF =  TIF_NextTIF(tTIF);                                      \
00446       if (!tTIF) xsb_exit("Trying to free nonexistent TIF");            \
00447       if ((pTIF) == private_tif_list.last) private_tif_list.last = tTIF; \
00448       TIF_NextTIF(tTIF) = TIF_NextTIF((pTIF));                          \
00449     }                                                                   \
00450     delete_predicate_table(CTXTc pTIF);                                 \
00451     mem_dealloc((pTIF),sizeof(TableInfoFrame),TABLE_SPACE);             \
00452   }
00453 
00454 /*===========================================================================*/
00455 
00456 /*
00457  *                         Table Dispatch Blocks
00458  *                         =======================
00459  *
00460  *  Table Information Frames are created in the multi-threaded engine
00461  *  to allow a single predicate to have multiple TIFs (and by
00462  *  extension tries), one for each thread.  A Table Dispatch Block
00463  *  stands between the outer TIF (to which tabletry(single)
00464  *  instructions point, and the per-predicate TIFs that are used to
00465  *  manage thread-private tables.
00466  */
00467 
00468 struct TDispBlk_t { /* first two fields must be same as Table_Info_Frame for coercion! */
00469   Psc psc_ptr;
00470   byte method; /* == DISPATCH_BLOCK for disp block, VARIANT/SUB for TIF */
00471   byte mark;                    /* eval pred using variant or subsumption? */
00472   struct TDispBlk_t *PrevDB;
00473   struct TDispBlk_t *NextDB;
00474   int MaxThread;
00475   TIFptr Thread0;       /* should probably call this tifarray */
00476 };
00477 typedef struct TDispBlk_t *TDBptr;
00478  
00479 #define TIF_DispatchBlock(pTIF)    ((TDBptr) (pTIF)->psc_ptr )
00480 #define TDB_MaxThread(pTDB)        ( (pTDB)->MaxThread )
00481 #define TDB_TIFArray(pTDB)         ( (&(pTDB)->Thread0) )
00482 #define TDB_PrivateTIF(pTDB,tid)    ( TDB_TIFArray(pTDB)[(tid)] )
00483 
00484 struct TDispBlkHdr_t {
00485   struct TDispBlk_t *firstDB;
00486   struct TDispBlk_t *lastDB;
00487 };
00488 
00489 /* If private predicate in MT engine, find the thread's private TIF,
00490    otherwise leave unchanged */
00491 #define  handle_dispatch_block(tip)                                     \
00492   if ( isPrivateTIF(tip) ) {                                            \
00493     TDBptr tdispblk;                                                    \
00494     tdispblk = (TDBptr) tip;                                            \
00495     if (th->tid > TDB_MaxThread(tdispblk))                              \
00496       xsb_abort("Table Dispatch block too small");                      \
00497     tip = TDB_PrivateTIF(tdispblk,th->tid);                             \
00498     if (!tip) {                                                         \
00499       /* this may not be possible, as it may always be initted in get_tip? */\
00500       tip = New_TIF(CTXTc tdispblk->psc_ptr);                   \
00501       TDB_PrivateTIF(tdispblk,th->tid) = tip;                           \
00502     }                                                                   \
00503   }
00504 
00505 /*===========================================================================*/
00506 
00507 typedef struct ascc_edge *EPtr;
00508 typedef struct completion_stack_frame *ComplStackFrame;
00509 
00510 /*----------------------------------------------------------------------*/
00511 /*  Approximate Strongly Connected Component Edge Structure.            */
00512 /*----------------------------------------------------------------------*/
00513 
00514 struct ascc_edge {
00515   ComplStackFrame ascc_node_ptr;
00516   EPtr next;
00517 };
00518 
00519 #define ASCC_EDGE_SIZE          (sizeof(struct ascc_edge)/sizeof(CPtr))
00520 
00521 #define edge_to_node(e)         ((EPtr)(e))->ascc_node_ptr
00522 #define next_edge(e)            ((EPtr)(e))->next
00523 
00524 /*----------------------------------------------------------------------*/
00525 /*  Completion Stack Structure (ASCC node structure).                   */
00526 /*                                                                      */
00527 /*  NOTE: Please make sure that fields "DG_edges" and "DGT_edges" are   */
00528 /*        the last fields of the structure, and each time you modify    */
00529 /*        this structure you also update the definition of the          */
00530 /*        "compl_stk_frame_field" array defined in file debug.c         */
00531 /*----------------------------------------------------------------------*/
00532 
00533 #define DELAYED         -1
00534 
00535 /*----------------------------------------------------------------------*/
00536 
00537 struct completion_stack_frame {
00538   VariantSF subgoal_ptr;
00539   int     _level_num;
00540   ALNptr  del_ret_list;   /* to reclaim deleted returns */
00541   int     visited;
00542 #ifndef LOCAL_EVAL
00543   EPtr    DG_edges;
00544   EPtr    DGT_edges;
00545 #endif
00546 #ifdef CONC_COMPL
00547   CPtr    ext_cons;
00548 #endif
00549 } ;
00550 
00551 #define COMPLFRAMESIZE  (sizeof(struct completion_stack_frame)/sizeof(CPtr))
00552 
00553 #define compl_subgoal_ptr(b)    ((ComplStackFrame)(b))->subgoal_ptr
00554 #define compl_level(b)          ((ComplStackFrame)(b))->_level_num
00555 #define compl_del_ret_list(b)   ((ComplStackFrame)(b))->del_ret_list
00556 #define compl_visited(b)        ((ComplStackFrame)(b))->visited
00557 #ifndef LOCAL_EVAL
00558 #define compl_DG_edges(b)       ((ComplStackFrame)(b))->DG_edges
00559 #define compl_DGT_edges(b)      ((ComplStackFrame)(b))->DGT_edges
00560 #endif
00561 #ifdef CONC_COMPL
00562 #define compl_ext_cons(b)       ((ComplStackFrame)(b))->ext_cons
00563 #endif
00564 
00565 #define prev_compl_frame(b)     (((CPtr)(b))+COMPLFRAMESIZE)
00566 #define next_compl_frame(b)     (((CPtr)(b))-COMPLFRAMESIZE)
00567 
00568 
00569 #define adjust_level(CS_FRAME) {                                        \
00570   int new_level = compl_level(CS_FRAME);                                \
00571   if ( new_level < compl_level(openreg) ) {                             \
00572     CPtr csf = CS_FRAME;                                                \
00573     while ( (compl_level(csf) >= new_level) && (csf >= openreg) ) {     \
00574       compl_level(csf) = new_level;                                     \
00575       csf = next_compl_frame(csf);                                      \
00576     }                                                                   \
00577   }                                                                     \
00578 }
00579 
00580 
00581 /*
00582  *  The overflow test MUST be placed after the initialization of the
00583  *  ComplStackFrame in the current implementation.  This is so that the
00584  *  corresponding subgoal which points to this frame can be found and its
00585  *  link can be updated if an expansion is required.  This was the simplest
00586  *  solution to not leaving any dangling pointers to the old area.
00587  */
00588 
00589 #define push_completion_frame_common(subgoal) \
00590   level_num++; \
00591   openreg -= COMPLFRAMESIZE; \
00592   compl_subgoal_ptr(openreg) = subgoal; \
00593   compl_level(openreg) = level_num; \
00594   compl_del_ret_list(openreg) = NULL; \
00595   compl_visited(openreg) = FALSE
00596 
00597 #define push_completion_frame_batched(subgoal) \
00598   compl_DG_edges(openreg) = compl_DGT_edges(openreg) = NULL
00599 
00600 #ifdef LOCAL_EVAL
00601 #define push_completion_frame(subgoal)  \
00602   push_completion_frame_common(subgoal); \
00603   check_completion_stack_overflow
00604 #else
00605 #define push_completion_frame(subgoal)  \
00606   push_completion_frame_common(subgoal); \
00607   push_completion_frame_batched(subgoal); \
00608   check_completion_stack_overflow
00609 #endif
00610 
00611 #if (!defined(LOCAL_EVAL))
00612 #define compact_completion_frame(cp_frame,cs_frame,subgoal)     \
00613   compl_subgoal_ptr(cp_frame) = subgoal;                        \
00614   compl_level(cp_frame) = compl_level(cs_frame);                \
00615   compl_visited(cp_frame) = FALSE;                              \
00616   compl_DG_edges(cp_frame) = compl_DGT_edges(cp_frame) = NULL;  \
00617   cp_frame = next_compl_frame(cp_frame)
00618 #endif
00619 
00620 /*----------------------------------------------------------------------*/
00621 /*  Subgoal (Call) Structure.                                           */
00622 /*----------------------------------------------------------------------*/
00623 
00624 #include "slgdelay.h"
00625 
00626 /*----------------------------------------------------------------------*/
00627 
00628 enum SubgoalFrameType {
00629   SHARED_VARIANT_PRODUCER_SFT        = 0x06,   /* binary 0110 */
00630   SHARED_SUBSUMPTIVE_PRODUCER_SFT    = 0x05,   /* binary 0101 */
00631   SHARED_SUBSUMED_CONSUMER_SFT       = 0x04,   /* binary 0100 */
00632   PRIVATE_VARIANT_PRODUCER_SFT       = 0x02,   /* binary 0010 */
00633   PRIVATE_SUBSUMPTIVE_PRODUCER_SFT   = 0x01,   /* binary 0001 */
00634   PRIVATE_SUBSUMED_CONSUMER_SFT      = 0x00    /* binary 0000 */
00635 };
00636 
00637 /* Private is default */
00638 #define VARIANT_PRODUCER_SFT   0x02
00639 #define SUBSUMPTIVE_PRODUCER_SFT   0x01
00640 #define SUBSUMED_CONSUMER_SFT   0x00
00641 
00642 #define VARIANT_SUBSUMPTION_MASK  0x03
00643 
00644 #define SHARED_PRIVATE_MASK 0x04
00645 #define SHARED_SFT 0x04
00646 #define PRIVATE_SFT 0x00
00647 
00648 /* --------------------------------
00649 
00650    Variant (Producer) Subgoal Frame
00651 
00652    Note that the cp_ptr, which is not needed until a table is
00653    complete, is reused as the pointer to the DelTF -- but the DelTF
00654    usage will occur only after the table has been completed, so its
00655    safe.
00656 
00657    -------------------------------- */
00658 
00659 typedef struct subgoal_frame {
00660   byte sf_type;           /* The type of subgoal frame */
00661   byte is_complete;       /* If producer, whether its answer set is complete */
00662   byte is_reclaimed;      /* Whether structs for supporting answer res from an
00663                              incomplete table have been reclaimed */
00664   TIFptr tif_ptr;         /* Table of which this call is a part */
00665   BTNptr leaf_ptr;        /* Handle for call in the CallTrie */
00666   BTNptr ans_root_ptr;    /* Root of the return trie */
00667   ALNptr ans_list_ptr;    /* Pointer to the list of returns in the ret trie */
00668   ALNptr ans_list_tail;   /* pointer to the tail of the answer list */
00669   void *next_subgoal;     
00670   void *prev_subgoal;
00671   CPtr  cp_ptr;           /* Pointer to the Generator CP */
00672   CPtr asf_list_ptr;      /* Pointer to list of (CP) active subgoal frames */
00673   CPtr compl_stack_ptr;   /* Pointer to subgoal's completion stack frame */
00674   CPtr compl_suspens_ptr; /* SLGWAM: CP stack ptr */
00675   PNDE nde_list;          /* pointer to a list of negative DEs */
00676   DelTFptr deltf_ptr;
00677 #ifdef MULTI_THREAD
00678   int tid;                /* Thread id of the generator thread for this sg */
00679 #endif
00680 #ifdef CONC_COMPL
00681   ALNptr tag;             /* Tag can't be stored in answer list in conc compl */
00682 #endif
00683 #ifdef SHARED_COMPL_TABLES
00684   byte grabbed;           /* Subgoal is marked to be computed for leader in
00685                              deadlock detection */
00686 #endif
00687 } variant_subgoal_frame;
00688 
00689 #define subg_sf_type(b)         ((VariantSF)(b))->sf_type
00690 #define subg_is_complete(b)     ((VariantSF)(b))->is_complete
00691 #define subg_is_reclaimed(b)    ((VariantSF)(b))->is_reclaimed
00692 #define subg_prev_subgoal(b)    ((VariantSF)(b))->prev_subgoal
00693 #define subg_next_subgoal(b)    ((VariantSF)(b))->next_subgoal
00694 #define subg_tif_ptr(b)         ((VariantSF)(b))->tif_ptr
00695 #define subg_leaf_ptr(b)        ((VariantSF)(b))->leaf_ptr
00696 #define subg_ans_root_ptr(b)    ((VariantSF)(b))->ans_root_ptr
00697 #define subg_ans_list_ptr(b)    ((VariantSF)(b))->ans_list_ptr
00698 #define subg_ans_list_tail(b)   ((VariantSF)(b))->ans_list_tail
00699 #define subg_cp_ptr(b)          ((VariantSF)(b))->cp_ptr
00700 #define subg_deltf_ptr(b)       ((VariantSF)(b))->deltf_ptr
00701 #define subg_asf_list_ptr(b)    ((VariantSF)(b))->asf_list_ptr
00702 
00703 /* use this for mark as completed == 0 */
00704 #define subg_compl_stack_ptr(b) ((VariantSF)(b))->compl_stack_ptr
00705 #define subg_compl_susp_ptr(b)  ((VariantSF)(b))->compl_suspens_ptr
00706 #define subg_nde_list(b)        ((VariantSF)(b))->nde_list
00707 
00708 #define subg_tid(b)             ((VariantSF)(b))->tid
00709 #define subg_tag(b)             ((VariantSF)(b))->tag
00710 #define subg_grabbed(b)         ((VariantSF)(b))->grabbed
00711 
00712 /* Subsumptive Producer Subgoal Frame
00713    ---------------------------------- */
00714 typedef struct SubsumedConsumerSubgoalFrame *SubConsSF;
00715 typedef struct SubsumptiveProducerSubgoalFrame *SubProdSF;
00716 typedef struct SubsumptiveProducerSubgoalFrame {
00717   variant_subgoal_frame  var_sf;
00718   SubConsSF  consumers;         /* List of properly subsumed subgoals which
00719                                    consume from a producer's answer set */
00720 } subsumptive_producer_sf;
00721 
00722 #define subg_consumers(SF)      ((SubProdSF)(SF))->consumers
00723 
00724 
00725 /* Subsumed Consumer Subgoal Frame
00726  * -------------------------------
00727  *  Position of shared fields MUST correspond to that of variant_subgoal_frame.
00728  */
00729 typedef struct SubsumedConsumerSubgoalFrame {
00730   byte sf_type;            /* The type of subgoal frame */
00731   byte junk[2];
00732   TIFptr tif_ptr;          /* Table of which this call is a part */
00733   BTNptr leaf_ptr;         /* Handle for call in the CallTrie */
00734   SubProdSF producer;      /* The subgoal frame from whose answer set answers
00735                               are collected into the answer list */
00736   ALNptr ans_list_ptr;     /* Pointer to the list of returns in the ret trie */
00737   ALNptr ans_list_tail;    /* Pointer to the tail of the answer list */
00738   TimeStamp ts;            /* Time stamp to use during next answer ident */
00739   SubConsSF consumers;     /* Chain link for properly subsumed subgoals */
00740 } subsumptive_consumer_sf;
00741 
00742 #define conssf_producer(SF)     ((SubConsSF)(SF))->producer
00743 #define conssf_timestamp(SF)    ((SubConsSF)(SF))->ts
00744 #define conssf_consumers(SF)    ((SubConsSF)(SF))->consumers
00745 
00746 
00747 /* beginning of REAL answers in the answer list */
00748 #define subg_answers(subg)      ALN_Next(subg_ans_list_ptr(subg))
00749 
00750 #define IsVariantSF(pSF) \
00751   ((subg_sf_type(pSF) & VARIANT_SUBSUMPTION_MASK) == VARIANT_PRODUCER_SFT)
00752 #define IsSubProdSF(pSF) \
00753   ((subg_sf_type(pSF) & VARIANT_SUBSUMPTION_MASK) == SUBSUMPTIVE_PRODUCER_SFT)
00754 #define IsSubConsSF(pSF) \
00755   ((subg_sf_type(pSF) & VARIANT_SUBSUMPTION_MASK) == SUBSUMED_CONSUMER_SFT)
00756 
00757 #define IsPrivateSF(pSF) \
00758   ((subg_sf_type(pSF) & SHARED_PRIVATE_MASK) == PRIVATE_SFT)
00759 #define IsSharedSF(pSF) \
00760   ((subg_sf_type(pSF) & SHARED_PRIVATE_MASK) == SHARED_SFT)
00761 
00762 #define IsVariantProducer(pSF)          IsVariantSF(pSF)
00763 #define IsSubsumptiveProducer(pSF)      IsSubProdSF(pSF)
00764 #define IsProperlySubsumed(pSF)         IsSubConsSF(pSF)
00765 
00766 #define IsProducingSubgoal(pSF)         \
00767    ( IsVariantProducer(pSF) || IsSubsumptiveProducer(pSF) )
00768 
00769 #define ProducerSubsumesSubgoals(pSF)   \
00770    ( IsSubsumptiveProducer(pSF) && IsNonNULL(subg_consumers(pSF)) )
00771 
00772 
00773 /* Doubly-linked lists of Producer Subgoal Frames
00774  * ----------------------------------------------
00775  * Manipulating a doubly-linked list maintained through fields
00776  * `prev' and `next'.
00777  */
00778 
00779 #define subg_dll_add_sf(pSF,Chain,NewChain) {   \
00780    subg_prev_subgoal(pSF) = NULL;               \
00781    subg_next_subgoal(pSF) = Chain;              \
00782    if ( IsNonNULL(Chain) )                      \
00783      subg_prev_subgoal(Chain) = pSF;            \
00784    NewChain = (VariantSF)pSF;                           \
00785  }
00786 
00787 #define subg_dll_remove_sf(pSF,Chain,NewChain) {                         \
00788    if ( IsNonNULL(subg_prev_subgoal(pSF)) ) {                            \
00789      subg_next_subgoal(subg_prev_subgoal(pSF)) = subg_next_subgoal(pSF); \
00790      NewChain = Chain;                                                   \
00791    }                                                                     \
00792    else                                                                  \
00793      NewChain = (VariantSF)subg_next_subgoal(pSF);                       \
00794    if ( IsNonNULL(subg_next_subgoal(pSF)) )                              \
00795      subg_prev_subgoal(subg_next_subgoal(pSF)) = subg_prev_subgoal(pSF); \
00796    subg_prev_subgoal(pSF) = subg_next_subgoal(pSF) = NULL;               \
00797  }
00798 
00799 
00800 #ifndef MULTI_THREAD
00801 extern ALNptr empty_return(VariantSF);
00802 #define empty_return_handle(SF) empty_return(SF)
00803 #else
00804 extern ALNptr empty_return(struct th_context *,VariantSF);
00805 #define empty_return_handle(SF) empty_return(th,SF)
00806 #endif
00807 
00808 /* Appending to the Answer List of a SF
00809    ------------------------------------ */
00810 #define SF_AppendNewAnswerList(pSF,pAnsList) {  \
00811                                                 \
00812    ALNptr pLast;                                \
00813                                                 \
00814    pLast = pAnsList;                            \
00815    while ( IsNonNULL(ALN_Next(pLast)) )         \
00816      pLast = ALN_Next(pLast);                   \
00817    SF_AppendToAnswerList(pSF,pAnsList,pLast);   \
00818  }
00819 
00820 #define SF_AppendNewAnswer(pSF,pAns)    SF_AppendToAnswerList(pSF,pAns,pAns)
00821 
00822 #define SF_AppendToAnswerList(pSF,pHead,pTail) {                        \
00823    if ( has_answers(pSF) )                                              \
00824      /*
00825       *  Insert new answer at the end of the answer list.
00826       */                                                                \
00827      ALN_Next(subg_ans_list_tail(pSF)) = pHead;                         \
00828    else                                                                 \
00829      /*
00830       * The dummy answer list node is the only node currently in the list.
00831       * It's pointed to by the head ptr, but the tail ptr is NULL.
00832       */                                                                \
00833      ALN_Next(subg_ans_list_ptr(pSF)) = pHead;                          \
00834    subg_ans_list_tail(pSF) = pTail;                                     \
00835  }
00836 
00837 
00838 /* Global Structure Management
00839    --------------------------- */
00840 #define SUBGOAL_FRAMES_PER_BLOCK    16
00841 
00842 extern struct Structure_Manager smVarSF;
00843 extern struct Structure_Manager smProdSF;
00844 extern struct Structure_Manager smConsSF;
00845 
00846 
00847 /* Subgoal Frame (De)Allocation
00848    ---------------------------- */
00849 
00850 /* NewProducerSF() is now a function, in tables.c */
00851 
00852 #define FreeProducerSF(SF) {                                    \
00853    subg_dll_remove_sf(SF,TIF_Subgoals(subg_tif_ptr(SF)),        \
00854                       TIF_Subgoals(subg_tif_ptr(SF)));          \
00855    if ( IsVariantSF(SF) ) {                                     \
00856      if (IsSharedSF(SF)) {                                      \
00857        SM_DeallocateSharedStruct(smVarSF,SF);                   \
00858      } else {                                                   \
00859        SM_DeallocateStruct(smVarSF,SF);                         \
00860      }                                                          \
00861    }                                                            \
00862    else                                                         \
00863      SM_DeallocateStruct(smProdSF,SF)                           \
00864  }
00865 
00866 
00867 /*
00868  *  Allocates and initializes a subgoal frame for a consuming subgoal: a
00869  *  properly subsumed call consuming from an incomplete producer.
00870  *  Consuming subgoals are NOT inserted into the subgoal chain
00871  *  maintained by the TIF, but instead are maintained by the producer in
00872  *  a private linked list.  Many fields of a consumer SF are left blank
00873  *  since it won't be used in the same way as those for producers.  Its
00874  *  main purpose is to maintain the answer list and the call form.  Just
00875  *  as for the producer, an answer-list node is allocated for pointing
00876  *  to a dummy answer node and inserted into the answer list.
00877  *
00878  *  Finally, some housekeeping is needed to support lazy creation of the
00879  *  auxiliary structures in the producer's answer TST.  If this is the
00880  *  first consumer for this producer, then create these auxiliary
00881  *  structures.
00882  */
00883 
00884 #ifndef MULTI_THREAD
00885 void tstCreateTSIs(TSTNptr);
00886 #define     tstCreateTSIs_handle(Producer) tstCreateTSIs(Producer) 
00887 #else
00888 void tstCreateTSIs(struct th_context *,TSTNptr);
00889 #define     tstCreateTSIs_handle(Producer) tstCreateTSIs(th,Producer) 
00890 #endif
00891 
00892 /* Private structure manager for subsumptive tables: no shared
00893    allocation needed */
00894 #define NewSubConsSF(SF,Leaf,TableInfo,Producer) {              \
00895                                                                 \
00896    void *pNewSF;                                                \
00897                                                                 \
00898    SM_AllocateStruct(smConsSF,pNewSF);                          \
00899    pNewSF = memset(pNewSF,0,sizeof(subsumptive_consumer_sf));   \
00900    subg_sf_type(pNewSF) = SUBSUMED_CONSUMER_SFT;                \
00901    subg_tif_ptr(pNewSF) = TableInfo;                            \
00902    subg_leaf_ptr(pNewSF) = Leaf;                                \
00903    CallTrieLeaf_SetSF(Leaf,pNewSF);                             \
00904    conssf_producer(pNewSF) = (SubProdSF)Producer;               \
00905    if ( ! ProducerSubsumesSubgoals(Producer) )                  \
00906      tstCreateTSIs_handle((TSTNptr)subg_ans_root_ptr(Producer));                \
00907    subg_ans_list_ptr(pNewSF) = empty_return_handle(pNewSF);             \
00908    conssf_timestamp(pNewSF) = CONSUMER_SF_INITIAL_TS;           \
00909    conssf_consumers(pNewSF) = subg_consumers(Producer);         \
00910    subg_consumers(Producer) = (SubConsSF)pNewSF;                \
00911    SF = (VariantSF)pNewSF;                                      \
00912 }
00913 
00914 /*----------------------------------------------------------------------*/
00915 /*----------------------------------------------------------------------*/
00916 
00917 #define set_min(a,b,c)  if (b < c) a = b; else a = c
00918 
00919 #define tab_level(SUBG_PTR)     \
00920         compl_level((subg_compl_stack_ptr(SUBG_PTR)))
00921 #define next_tab_level(CSF_PTR) \
00922         compl_level(prev_compl_frame(CSF_PTR))
00923 
00924 #define is_leader(CSF_PTR)      \
00925         (next_tab_level(CSF_PTR) < compl_level(CSF_PTR))
00926 
00927 /*----------------------------------------------------------------------*/
00928 /* Codes for completed subgoals (assigned to subg_answers)              */
00929 /*----------------------------------------------------------------------*/
00930 
00931 #define NO_ANSWERS      (ALNptr)0
00932 #define UNCOND_ANSWERS  (ALNptr)1
00933 #define COND_ANSWERS    (ALNptr)2
00934 #define INCOMP_ANSWERS  (ALNptr)3
00935 
00936 /*----------------------------------------------------------------------*/
00937 /* The following 2 macros are to be used for incomplete subgoals.       */
00938 /*----------------------------------------------------------------------*/
00939 
00940 #define has_answers(SUBG_PTR)       IsNonNULL(subg_answers(SUBG_PTR))
00941 #define has_no_answers(SUBG_PTR)    IsNULL(subg_answers(SUBG_PTR))
00942 
00943 /*----------------------------------------------------------------------*/
00944 /* The following 5 macros should be used only for completed subgoals.   */
00945 /*----------------------------------------------------------------------*/
00946 
00947 /*
00948  * These defs depend on when the root of an answer trie is created.
00949  * Currently, this is when the first answer is added to the set.  They
00950  * are also dependent upon representation of the truth of ground goals.
00951  * Currently, true subgoals have an ESCAPE node placed below the root,
00952  * while false goals have no root nor leaves (since no answer was ever
00953  * inserted, there was no opportunity to create a root).
00954  */
00955 #define has_answer_code(SUBG_PTR)                               \
00956         ( IsNonNULL(subg_ans_root_ptr(SUBG_PTR)) &&             \
00957           IsNonNULL(BTN_Child(subg_ans_root_ptr(SUBG_PTR))) )
00958 
00959 #define subgoal_fails(SUBG_PTR)                 \
00960         ( ! has_answer_code(SUBG_PTR) )
00961 
00962 /* should only be used on ground subgoals (is for escape node inspection) */
00963 #define subgoal_unconditionally_succeeds(SUBG_PTR)                          \
00964         ( has_answer_code(SUBG_PTR) &&                                      \
00965           is_unconditional_answer(BTN_Child(subg_ans_root_ptr(SUBG_PTR))) )
00966 
00967 #define mark_subgoal_failed(SUBG_PTR)   \
00968         (subg_ans_root_ptr(SUBG_PTR) = NULL)
00969 
00970 #define neg_simplif_possible(SUBG_PTR)  \
00971         ((subgoal_fails(SUBG_PTR)) && (subg_nde_list(SUBG_PTR) != NULL))
00972 
00973 /*----------------------------------------------------------------------*/
00974 
00975 #define is_completed(SUBG_PTR)          subg_is_complete(SUBG_PTR)
00976 
00977 #define structs_are_reclaimed(SUBG_PTR) subg_is_reclaimed(SUBG_PTR)
00978 
00979 #ifndef MULTI_THREAD   
00980 #define mark_as_completed(SUBG_PTR) {           \
00981           subg_is_complete(SUBG_PTR) = TRUE;    \
00982           reclaim_del_ret_list(SUBG_PTR);       \
00983         }
00984 #else
00985 #define mark_as_completed(SUBG_PTR) {           \
00986           subg_is_complete(SUBG_PTR) = TRUE;    \
00987           reclaim_del_ret_list(th, SUBG_PTR);   \
00988         }
00989 #endif
00990 
00991 #define subgoal_space_has_been_reclaimed(SUBG_PTR,CS_FRAME) \
00992         (SUBG_PTR != compl_subgoal_ptr(CS_FRAME))
00993 
00994 #define mark_delayed(csf1, csf2, susp) { \
00995           compl_visited(csf1) = DELAYED; \
00996           compl_visited(csf2) = DELAYED; \
00997   /* do not put TRUE but some !0 value that GC can recognize as int tagged */\
00998           csf_neg_loop(susp) = XSB_INT; \
00999         }
01000 
01001 /*----------------------------------------------------------------------*/
01002 /* The following macro might be called more than once for some subgoal. */
01003 /* So, please make sure that functions/macros that it calls are robust  */
01004 /* under repeated uses.                                 - Kostis.       */
01005 /* A new Subgoal Frame flag prevents multiple calls.    - Ernie         */
01006 /*----------------------------------------------------------------------*/
01007 
01008 #ifndef MULTI_THREAD
01009 #define reclaim_incomplete_table_structs(SUBG_PTR) {    \
01010    if ( ! structs_are_reclaimed(SUBG_PTR) ) {           \
01011      table_complete_entry(SUBG_PTR);                    \
01012      structs_are_reclaimed(SUBG_PTR) = TRUE;            \
01013    }                                                    \
01014  }
01015 #else
01016 #define reclaim_incomplete_table_structs(SUBG_PTR) {    \
01017    if ( ! structs_are_reclaimed(SUBG_PTR) ) {           \
01018      table_complete_entry(th, SUBG_PTR);                        \
01019      structs_are_reclaimed(SUBG_PTR) = TRUE;            \
01020    }                                                    \
01021  }
01022 #endif
01023 
01024 /*----------------------------------------------------------------------*/
01025 #ifdef DEMAND
01026 #define Reset_Demand_Freeze_Registers \
01027     bdfreg = bfreg; \
01028     trdfreg = trfreg; \
01029     hdfreg = hfreg; \
01030     edfreg = efreg
01031 #else
01032 #define Reset_Demand_Freeze_Registers 
01033 #endif
01034 
01035 #define reset_freeze_registers \
01036     bfreg = (CPtr)(tcpstack.high) - CP_SIZE; \
01037     trfreg = (CPtr *)(tcpstack.low); \
01038     hfreg = (CPtr)(glstack.low); \
01039     efreg = (CPtr)(glstack.high) - 1; \
01040     level_num = xwammode = 0; \
01041     root_address = ptcpreg = NULL; \
01042     Reset_Demand_Freeze_Registers
01043 
01044 #define adjust_freeze_registers(tcp) \
01045     if (bfreg < tcp_bfreg(tcp)) { bfreg = tcp_bfreg(tcp); }      \
01046     if (trfreg > tcp_trfreg(tcp)) { trfreg = tcp_trfreg(tcp); }\
01047     if (hfreg > tcp_hfreg(tcp)) { hfreg = tcp_hfreg(tcp); }      \
01048     if (efreg < tcp_efreg(tcp)) { efreg = tcp_efreg(tcp); }
01049 
01050 #define reclaim_stacks(tcp) \
01051   if (tcp == root_address) { \
01052     reset_freeze_registers; \
01053     /* xsb_dbgmsg("reset registers...."); */ \
01054   } \
01055   else { \
01056     adjust_freeze_registers(tcp); \
01057     /* xsb_dbgmsg(adjust registers...."); */ \
01058   }
01059 
01060 /*----------------------------------------------------------------------*/
01061 
01062 #define pdlpush(cell)   *(pdlreg) = cell;  pdlreg--
01063 
01064 #define pdlpop          *(++pdlreg)
01065 
01066 #define pdlempty        (pdlreg == (CPtr)(pdl.high) - 1)
01067 
01068 #define resetpdl \
01069    if (pdlreg < (CPtr) pdl.low) \
01070      xsb_exit("pdlreg grew too much"); \
01071    else (pdlreg = (CPtr)(pdl.high) - 1)
01072 
01073 #define remove_incomplete_tables_loop(Endpoint) remove_incomplete_tries(Endpoint)
01074 
01075 #define remove_incomplete_tables() remove_incomplete_tries(CTXTc COMPLSTACKBOTTOM)
01076 
01077 /*----------------------------------------------------------------------*/
01078 
01079 #define get_var_and_attv_nums(var_num, attv_num, tmp_int)       \
01080   var_num = tmp_int & 0xffff;                                   \
01081   attv_num = tmp_int >> 16
01082 
01083 /*----------------------------------------------------------------------*/
01084 
01085 #endif /* __MACRO_XSB_H__ */

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