tries.c

00001 /* File:      tries.c
00002 ** Author(s): Prasad Rao, David S. Warren, Kostis Sagonas,
00003 **            Juliana Freire, Baoqiu Cui
00004 ** Contact:   xsb-contact@cs.sunysb.edu
00005 ** 
00006 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00007 ** Copyright (C) ECRC, Germany, 1990
00008 ** 
00009 ** XSB is free software; you can redistribute it and/or modify it under the
00010 ** terms of the GNU Library General Public License as published by the Free
00011 ** Software Foundation; either version 2 of the License, or (at your option)
00012 ** any later version.
00013 ** 
00014 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00015 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00016 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00017 ** more details.
00018 ** 
00019 ** You should have received a copy of the GNU Library General Public License
00020 ** along with XSB; if not, write to the Free Software Foundation,
00021 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022 **
00023 ** $Id: tries.c,v 1.87 2006/05/22 14:53:44 dwarren Exp $
00024 ** 
00025 */
00026 
00027 
00028 #include "xsb_config.h"
00029 #include "xsb_debug.h"
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 
00034 /* Special debug includes */
00035 #include "debugs/debug_tries.h"
00036 
00037 #include "auxlry.h"
00038 #include "cell_xsb.h"
00039 #include "inst_xsb.h"
00040 #include "psc_xsb.h"
00041 #include "heap_xsb.h"
00042 #include "flags_xsb.h"
00043 #include "deref.h"
00044 #include "memory_xsb.h"
00045 #include "register.h"
00046 #include "binding.h"
00047 #include "trie_internals.h"
00048 #include "macro_xsb.h"
00049 #include "choice.h"
00050 #include "cinterf.h"
00051 #include "error_xsb.h"
00052 #include "tr_utils.h"
00053 #include "rw_lock.h"
00054 #include "thread_xsb.h"
00055 #include "debug_xsb.h"
00056 #include "subp.h"
00057 
00058 /*----------------------------------------------------------------------*/
00059 /* The following variables are used in other parts of the system        */
00060 /*----------------------------------------------------------------------*/
00061 
00062 long subg_chk_ins, subg_inserts, ans_chk_ins, ans_inserts; /* statistics */
00063 
00064 #ifndef MULTI_THREAD
00065 int  num_heap_term_vars;
00066 CPtr *var_addr;
00067 int  var_addr_arraysz;
00068 Cell VarEnumerator[NUM_TRIEVARS];
00069 Cell TrieVarBindings[NUM_TRIEVARS];
00070 #endif
00071 
00072 /* xsbBool check_table_cut = TRUE;  flag for close_open_tables to turn off
00073                                     cut-over-table check */
00074 
00075 /*
00076  * global_num_vars is a new variable to save the value of variable
00077  * num_vars_in_var_regs temporarily.
00078  */
00079 #ifndef MULTI_THREAD
00080 int global_num_vars;
00081 #endif
00082 
00083 /*
00084  * Array VarEnumerator_trail[] is used to trail the variable bindings when we
00085  * copy terms into tries.  The variables trailed using VarEnumerator_trail are
00086  * those that are bound to elements in VarEnumerator[].
00087  */
00088 #ifndef MULTI_THREAD
00089 static CPtr VarEnumerator_trail[NUM_TRIEVARS];
00090 static CPtr *VarEnumerator_trail_top;
00091 #endif
00092 
00093 
00094 char *trie_node_type_table[] = {"interior_nt","hashed_interior_nt","leaf_nt",
00095                            "hashed_leaf_nt","hash_header_nt","undefined",
00096                            "undefined","undefined","trie_root_nt"};
00097 
00098 char *trie_trie_type_table[] = {"call_trie_tt","basic_answer_trie_tt",
00099                                 "ts_answer_trie_tt","delay_trie_tt",
00100                                 "assert_trie_tt","intern_trie_tt"
00101 };
00102 
00103 /*----------------------------------------------------------------------*/
00104 /* Safe assignment -- can be generalized by type.
00105    CPtr can be abstracted out */
00106 #define safe_assign(ArrayNam,Index,Value,ArraySz) {\
00107    if (Index >= ArraySz) {\
00108      trie_expand_array(CPtr,ArrayNam,ArraySz,Index,"var_addr");\
00109    }\
00110    ArrayNam[Index] = Value;\
00111 }
00112 
00113 /*----------------------------------------------------------------------*/
00114 /*****************Addr Stack************* 
00115 
00116  TLS 08/05: The addr_stack and term_stack (below) are used by
00117  answer_return.  to copy information out of a trie and into a ret/n
00118  structure.  Its also used by table predicates to get delay lists.
00119 
00120  */
00121 
00122 #ifndef MULTI_THREAD
00123 static int addr_stack_pointer = 0;
00124 static CPtr *Addr_Stack;
00125 static int addr_stack_size    = DEFAULT_ARRAYSIZ;
00126 #endif
00127 
00128 #define pop_addr Addr_Stack[--addr_stack_pointer]
00129 #define push_addr(X) {\
00130     if (addr_stack_pointer == addr_stack_size) {\
00131        trie_expand_array(CPtr, Addr_Stack ,addr_stack_size,0,"Addr_Stack");\
00132     }\
00133     Addr_Stack[addr_stack_pointer++] = ((CPtr) X);\
00134 }
00135 
00136 /*----------------------------------------------------------------------*/
00137 /*****************Term Stack*************/
00138 #ifndef MULTI_THREAD
00139 static int  term_stackptr = -1;
00140 static Cell *term_stack;
00141 static long term_stacksize = DEFAULT_ARRAYSIZ;
00142 #endif
00143 
00144 #define pop_term term_stack[term_stackptr--]
00145 #define push_term(T) {\
00146     if (term_stackptr+1 == term_stacksize) {\
00147        trie_expand_array(Cell,term_stack,term_stacksize,0,"term_stack");\
00148     }\
00149     term_stack[++term_stackptr] = ((Cell) T);\
00150 }
00151 
00152 /*----------------------------------------------------------------------*/
00153 /*********Simpler trails ****************/
00154 
00155 #define simple_table_undo_bindings              \
00156     while (VarEnumerator_trail_top >= VarEnumerator_trail) {    \
00157         untrail(*VarEnumerator_trail_top);              \
00158         VarEnumerator_trail_top--;                      \
00159     }   
00160 
00161 #define StandardizeAndTrailVariable(addr,n)     \
00162    StandardizeVariable(addr,n);                 \
00163     *(++VarEnumerator_trail_top) = addr;
00164                 
00165 /*----------------------------------------------------------------------*/
00166 /* Variables used only in this file                                     */
00167 /*----------------------------------------------------------------------*/
00168 
00169 static BasicTrieNode dummy_ans_node = {{0,1,0,0},NULL,NULL,NULL,0};
00170 
00171 #ifndef MULTI_THREAD
00172 static int AnsVarCtr;
00173 #endif
00174 
00175 /*----------------------------------------------------------------------*/
00176 
00177 /*
00178  *          T R I E   S T R U C T U R E   M A N A G E M E N T
00179  *          =================================================
00180  */
00181 char *TrieSMNameTable[] = {"Basic Trie Node (Private)",
00182                    "Basic Trie Hash Table (Private)"};
00183 
00184 /* For Call and Answer Tries
00185    ------------------------- */
00186 
00187 Structure_Manager smTableBTN  = SM_InitDecl(BasicTrieNode, BTNs_PER_BLOCK,
00188                                             "Basic Trie Node");
00189 Structure_Manager smTableBTHT = SM_InitDecl(BasicTrieHT, BTHTs_PER_BLOCK,
00190                                             "Basic Trie Hash Table");
00191 
00192 /* For Assert & Intern Tries
00193    ------------------------- */
00194 Structure_Manager smAssertBTN  = SM_InitDecl(BasicTrieNode, BTNs_PER_BLOCK,
00195                                              "Basic Trie Node");
00196 Structure_Manager smAssertBTHT = SM_InitDecl(BasicTrieHT, BTHTs_PER_BLOCK,
00197                                              "Basic Trie Hash Table");
00198 
00199 /* Maintains Current Structure Space
00200    --------------------------------- */
00201 
00202 /* MT engine uses both shared and private structure managers,
00203    sequential engine doesn't.  In addition, in MT engine, all
00204    subsumptive tables are private, thus use subsumptive_smBTN/BTHT for
00205    structure managers common to both variant and private tables. */
00206 
00207 #ifndef MULTI_THREAD
00208 Structure_Manager smTSTN      = SM_InitDecl(TS_TrieNode, TSTNs_PER_BLOCK,
00209                                             "Time-Stamped Trie Node");
00210 Structure_Manager smTSTHT     = SM_InitDecl(TST_HashTable, TSTHTs_PER_BLOCK,
00211                                             "Time-Stamped Trie Hash Table");
00212 Structure_Manager smTSIN      = SM_InitDecl(TS_IndexNode, TSINs_PER_BLOCK,
00213                                             "Time-Stamp Indexing Node");
00214 
00215 Structure_Manager *smBTN = &smTableBTN;
00216 Structure_Manager *smBTHT = &smTableBTHT;
00217 
00218 #endif
00219 
00220 
00221 /*----------------------------------------------------------------------*/
00222 
00223 void init_trie_aux_areas(CTXTdecl)
00224 {
00225   int i;
00226 
00227   /* TLS: commented these out to catch private/shared bugs more
00228      quickly */
00229 #ifndef MULTI_THREAD
00230   smBTN = &smTableBTN;
00231   smBTHT = &smTableBTHT;
00232 #endif
00233 
00234   addr_stack_size = 0;
00235   Addr_Stack = NULL;
00236   addr_stack_pointer = 0;
00237 
00238   term_stacksize = 0;
00239   term_stack = NULL;
00240   term_stackptr = -1;
00241 
00242   var_addr_arraysz = 0;
00243   var_addr = NULL;
00244 
00245   reg_array = NULL;
00246   reg_array_size = 0;
00247   reg_arrayptr = reg_array -1;
00248 
00249   for (i = 0; i < NUM_TRIEVARS; i++)
00250     VarEnumerator[i] = (Cell) & (VarEnumerator[i]);
00251 }
00252 
00253 void free_trie_aux_areas(CTXTdecl)
00254 {
00255   mem_dealloc(term_stack,term_stacksize,TABLE_SPACE);
00256   mem_dealloc(var_addr,var_addr_arraysz,TABLE_SPACE);
00257   mem_dealloc(Addr_Stack,addr_stack_size,TABLE_SPACE);
00258   mem_dealloc(reg_array,reg_array_size,TABLE_SPACE);
00259 }
00260 
00261 /*-------------------------------------------------------------------------*/
00262 
00263 BTNptr new_btn(CTXTdeclc int trie_t, int node_t, Cell symbol, BTNptr parent,
00264                BTNptr sibling) {
00265 
00266   void *btn;
00267 
00268 #ifdef MULTI_THREAD  
00269   if (threads_current_sm == PRIVATE_SM) {
00270     SM_AllocateStruct(*smBTN,btn);
00271   } else {
00272     SM_AllocateSharedStruct(*smBTN,btn);
00273     }
00274 #else
00275   SM_AllocateStruct(*smBTN,btn);
00276 #endif
00277   TN_Init(((BTNptr)btn),trie_t,node_t,symbol,parent,sibling);
00278   return (BTNptr)btn;
00279 }
00280 
00281 /*-------------------------------------------------------------------------*/
00282 
00283 TSTNptr new_tstn(CTXTdeclc int trie_t, int node_t, Cell symbol, TSTNptr parent,
00284                 TSTNptr sibling) {
00285 
00286   void * tstn;
00287 
00288   SM_AllocateStruct(smTSTN,tstn);
00289   TN_Init(((TSTNptr)tstn),trie_t,node_t,symbol,parent,sibling);
00290   TSTN_TimeStamp(((TSTNptr)tstn)) = TSTN_DEFAULT_TIMESTAMP;
00291   return (TSTNptr)tstn;
00292 }
00293 
00294 /*-------------------------------------------------------------------------*/
00295 
00296 /*
00297  * Creates a root node for a given type of trie.
00298  */
00299 
00300 BTNptr newBasicTrie(CTXTdeclc Cell symbol, int trie_type) {
00301 
00302   BTNptr pRoot;
00303 
00304   New_BTN( pRoot, trie_type, TRIE_ROOT_NT, symbol, NULL, NULL );
00305   return pRoot;
00306 }
00307 
00308 /*-------------------------------------------------------------------------*/
00309 
00310 /*
00311  * Creates a root node for a given type of trie.  Differs from above in that
00312  * the parent is intended to be set to the subgoal frame.
00313  */
00314 
00315 BTNptr newBasicAnswerTrie(CTXTdeclc Cell symbol, CPtr Paren, int trie_type) {
00316 
00317   BTNptr pRoot;
00318 
00319   New_BTN( pRoot, trie_type, TRIE_ROOT_NT, symbol, Paren, NULL );
00320   return pRoot;
00321 }
00322 
00323 /*----------------------------------------------------------------------*/
00324 
00325 /* Used by one_node_chk_ins only. */
00326 #define IsInsibling(wherefrom,count,Found,item,TrieType)                \
00327 {                                                                       \
00328   LocalNodePtr = wherefrom;                                             \
00329   while (LocalNodePtr && (BTN_Symbol(LocalNodePtr) != item)) {          \
00330     LocalNodePtr = BTN_Sibling(LocalNodePtr);                           \
00331     count++;                                                            \
00332   }                                                                     \
00333   if ( IsNULL(LocalNodePtr) ) {                                         \
00334     Found = 0;                                                          \
00335     New_BTN(LocalNodePtr,TrieType,INTERIOR_NT,item,Paren,wherefrom);    \
00336     count++;                                                            \
00337     wherefrom = LocalNodePtr;  /* hook the new node into the trie */    \
00338   }                                                                     \
00339   Paren = LocalNodePtr;                                                 \
00340 }
00341 
00342 
00343 /*
00344  *  Insert/find a single symbol in the trie structure 1-level beneath a
00345  *  parent NODE, pointed to by `Paren', whose child link field is
00346  *  pointed to by 'GNodePtrPtr'.  (If 'Paren' is NULL, then we are most
00347  *  likely searching beneath some other structure, like the TIP, and
00348  *  'GNodePtrPtr' points to its "trie root" field.)  If the symbol
00349  *  cannot be found, create a NODE for this symbol and make it the child
00350  *  of `Paren' by setting the field that 'GNodePtrPtr' points to to this
00351  *  new NODE.  Upon exiting this macro, 'Paren' is set to point to the
00352  *  node containing this symbol and 'GNodePtrPtr' gets the address of
00353  *  this nodes' Child field.
00354  *
00355  *  Algorithm:
00356  *  ---------
00357  *  If the parent has no children, then create a node for the symbol
00358  *  and link it to the parent and vice versa.  Set the `Found' flag to
00359  *  indicate that a new node was necessary.
00360  *
00361  *  Otherwise, if the parent utilizes a hash structure for maintaining
00362  *  its children, check to see if there is enough room for one more
00363  *  entry.  If not, then expand the hash structure.  Search for the
00364  *  node containing the symbol in question, inserting it if it is not
00365  *  found.  Signify through `Found' the result of this action.
00366  *
00367  *  Otherwise, look for the symbol in a normal chain of children
00368  *  beneath the parent.  If it is not found, then insert it and check
00369  *  to see if the chain has now become too long; if so, then create a
00370  *  hash structure for the parent's children.  Signify through `Found'
00371  *  the result of this action.
00372  *
00373  *  Prepare for the next insertion/lookup by changing the `hook' to
00374  *  that of the child pointer field of the node which contains the
00375  *  just-processed symbol.
00376  */
00377 
00378 #define one_node_chk_ins(Found,item,TrieType) {                         \
00379                                                                         \
00380    int count = 0;                                                       \
00381    BTNptr LocalNodePtr;                                                 \
00382                                                                         \
00383    TRIE_W_LOCK();                                                       \
00384    if ( IsNULL(*GNodePtrPtr) ) {                                        \
00385      New_BTN(LocalNodePtr,TrieType,INTERIOR_NT,item,Paren,NULL);        \
00386      *GNodePtrPtr = Paren = LocalNodePtr;                               \
00387      Found = 0;                                                         \
00388    }                                                                    \
00389    else if ( IsHashHeader(*GNodePtrPtr) ) {                             \
00390      BTHTptr ht = (BTHTptr)*GNodePtrPtr;                                \
00391      GNodePtrPtr = CalculateBucketForSymbol(ht,item);                   \
00392      IsInsibling(*GNodePtrPtr,count,Found,item,TrieType);               \
00393      if (!Found) {                                                      \
00394        MakeHashedNode(LocalNodePtr);                                    \
00395        BTHT_NumContents(ht)++;                                          \
00396        TrieHT_ExpansionCheck(ht,count);                                 \
00397      }                                                                  \
00398    }                                                                    \
00399    else {                                                               \
00400      BTNptr pParent = Paren;                                            \
00401      IsInsibling(*GNodePtrPtr,count,Found,item,TrieType);               \
00402      if (IsLongSiblingChain(count))                                     \
00403        /* used to pass in GNodePtrPtr (ptr to hook) */                  \
00404        hashify_children(CTXTc pParent,TrieType);                        \
00405    }                                                                    \
00406    GNodePtrPtr = &(BTN_Child(LocalNodePtr));                            \
00407    TRIE_W_UNLOCK();                                                     \
00408 }
00409 
00410 /*----------------------------------------------------------------------*/
00411 
00412 /* Trie-HashTable maintenance routines.
00413    ------------------------------------
00414    parentHook is the address of a field in some structure (should now be
00415    another trie node as all tries now have roots) which points to a chain
00416    of trie nodes whose length has become "too long."
00417 */
00418 
00419 void hashify_children(CTXTdeclc BTNptr parent, int trieType) {
00420 
00421   BTNptr children;              /* child list of the parent */
00422   BTNptr btn;                   /* current child for processing */
00423   BTHTptr ht;                   /* HT header struct */
00424   BTNptr *tablebase;            /* first bucket of allocated HT */
00425   unsigned long  hashseed;      /* needed for hashing of BTNs */
00426 
00427 
00428   New_BTHT(ht,trieType);
00429   children = BTN_Child(parent);
00430   BTN_SetHashHdr(parent,ht);
00431   tablebase = BTHT_BucketArray(ht);
00432   hashseed = BTHT_GetHashSeed(ht);
00433   for (btn = children;  IsNonNULL(btn);  btn = children) {
00434     children = BTN_Sibling(btn);
00435     TrieHT_InsertNode(tablebase, hashseed, btn);
00436     MakeHashedNode(btn);
00437   }
00438 }
00439 
00440 /*-------------------------------------------------------------------------*/
00441 
00442 /*
00443  *  Expand the hash table pointed to by 'pHT'.  Note that we can do this
00444  *  in place by using realloc() and noticing that, since the hash tables
00445  *  and hashing function are based on powers of two, a node existing in
00446  *  a bucket will either remain in that bucket -- in the lower part of
00447  *  the new table -- or jump to a corresponding bucket in the upper half
00448  *  of the expanded table.  This function can serve for all types of
00449  *  tries since only fields contained in a Basic Trie Hash Table are
00450  *  manipulated.
00451  *
00452  *  As expansion is a method for reducing access time and is not a
00453  *  critical operation, if the table cannot be expanded at this time due
00454  *  to memory limitations, then simply return.  Otherwise, initialize
00455  *  the top half of the new area, and rehash each node in the buckets of
00456  *  the lower half of the table.
00457  */
00458 
00459 
00460 void expand_trie_ht(BTHTptr pHT) {
00461 
00462   BTNptr *bucket_array;     /* base address of resized hash table */
00463   BTNptr *upper_buckets;    /* marker in the resized HT delimiting where the
00464                                 newly allocated buckets begin */
00465 
00466   BTNptr *bucket;           /* for stepping through buckets of the HT */
00467 
00468   BTNptr curNode;           /* TSTN being processed */
00469   BTNptr nextNode;          /* rest of the TSTNs in a bucket */
00470 
00471   unsigned long  new_size;  /* double duty: new HT size, then hash mask */
00472 
00473 
00474   new_size = TrieHT_NewSize(pHT);
00475   bucket_array = (BTNptr *)mem_realloc( BTHT_BucketArray(pHT), BTHT_NumBuckets(pHT)*sizeof(void*),
00476                                      new_size * sizeof(BTNptr),TABLE_SPACE );
00477   if ( IsNULL(bucket_array) )
00478     return;
00479 
00480   upper_buckets = bucket_array + BTHT_NumBuckets(pHT);
00481   for (bucket = upper_buckets;  bucket < bucket_array + new_size;  bucket++)
00482     *bucket = NULL;
00483   BTHT_NumBuckets(pHT) = new_size;
00484   new_size--;     /* 'new_size' is now the hashing mask */
00485   BTHT_BucketArray(pHT) = bucket_array;
00486   for (bucket = bucket_array;  bucket < upper_buckets;  bucket++) {
00487     curNode = *bucket;
00488     *bucket = NULL;
00489     while ( IsNonNULL(curNode) ) {
00490       nextNode = TN_Sibling(curNode);
00491       TrieHT_InsertNode(bucket_array, new_size, curNode);
00492       curNode = nextNode;
00493     }
00494   }
00495 }
00496 
00497 /*----------------------------------------------------------------------*/
00498 
00499 /*
00500  * Push the symbols along the path from the leaf to the root in a trie
00501  * onto the termstack.
00502  */
00503 static void follow_par_chain(CTXTdeclc BTNptr pLeaf)
00504 {
00505   term_stackptr = -1; /* Forcibly Empty term_stack */
00506   while ( IsNonNULL(pLeaf) && (! IsTrieRoot(pLeaf)) ) {
00507     push_term((BTN_Symbol(pLeaf)));
00508     pLeaf = BTN_Parent(pLeaf);
00509   }
00510 }
00511 
00512 /*----------------------------------------------------------------------*/
00513 
00514 /*
00515  * Given a hook to an answer-list node, returns the answer contained in
00516  * that node and updates the hook to the next node in the chain.
00517  */
00518 BTNptr get_next_trie_solution(ALNptr *NextPtrPtr)
00519 {
00520   BTNptr TempPtr;
00521 
00522   TempPtr = ALN_Answer(*NextPtrPtr);
00523   *NextPtrPtr = ALN_Next(*NextPtrPtr);
00524   return(TempPtr);
00525 }
00526 
00527 /*----------------------------------------------------------------------*/
00528 
00529 #define rec_macro_make_heap_term(Macro_addr) {                          \
00530   int rj,rArity;                                                        \
00531   while(addr_stack_pointer) {                                           \
00532     Macro_addr = (CPtr)pop_addr;                                        \
00533     xtemp2 = pop_term;                                                  \
00534     switch( TrieSymbolType(xtemp2) ) {                                  \
00535     case XSB_TrieVar: {                                                 \
00536       int index = DecodeTrieVar(xtemp2);                                \
00537       if (IsNewTrieVar(xtemp2)) {                                       \
00538         safe_assign(var_addr,index,Macro_addr,var_addr_arraysz);        \
00539         num_heap_term_vars++;                                           \
00540       }                                                                 \
00541       else if (IsNewTrieAttv(xtemp2)) {                                 \
00542         safe_assign(var_addr,index,                                     \
00543                     (CPtr) makeattv(hreg),var_addr_arraysz);            \
00544         num_heap_term_vars++;                                           \
00545         new_heap_free(hreg);                                            \
00546         push_addr(hreg);                                                \
00547         hreg++;                                                         \
00548       }                                                                 \
00549       *Macro_addr = (Cell) var_addr[index];                             \
00550     }                                                                   \
00551     break;                                                              \
00552     case XSB_STRING:                                                    \
00553     case XSB_INT:                                                       \
00554     case XSB_FLOAT:                                                     \
00555       *Macro_addr = xtemp2;                                             \
00556       break;                                                            \
00557     case XSB_LIST:                                                      \
00558       *Macro_addr = (Cell) makelist(hreg);                              \
00559       hreg += 2;                                                        \
00560       push_addr(hreg-1);                                                \
00561       push_addr(hreg-2);                                                \
00562       break;                                                            \
00563     case XSB_STRUCT:                                                    \
00564       *Macro_addr = (Cell) makecs(hreg);                                \
00565       xtemp2 = (Cell) DecodeTrieFunctor(xtemp2);                        \
00566       *hreg = xtemp2;                                                   \
00567       rArity = (int) get_arity((Psc) xtemp2);                           \
00568       for (rj= rArity; rj >= 1; rj --) {                                \
00569         push_addr(hreg+rj);                                             \
00570       }                                                                 \
00571       hreg += rArity;                                                   \
00572       hreg++;                                                           \
00573       break;                                                            \
00574     default:                                                            \
00575       xsb_abort("Bad tag in macro_make_heap_term");                     \
00576       return;                                                           \
00577     }                                                                   \
00578   }                                                                     \
00579   if (top_of_localstk < top_of_heap) xsb_abort("Heap overflow: should expand"); \
00580 }
00581 
00582 /*----------------------------------------------------------------------*/
00583 
00584 #define macro_make_heap_term(ataddr,ret_val,dummy_addr) {               \
00585   int mArity,mj;                                                        \
00586   xtemp2 = pop_term;                                                    \
00587   switch( TrieSymbolType(xtemp2) ) {                                    \
00588   case XSB_TrieVar: {                                                   \
00589     int index = DecodeTrieVar(xtemp2);                                  \
00590     if (IsNewTrieVar(xtemp2)) { /* diff with CHAT - Kostis */           \
00591       safe_assign(var_addr,index,ataddr,var_addr_arraysz);              \
00592       num_heap_term_vars++;                                             \
00593     }                                                                   \
00594     else if (IsNewTrieAttv(xtemp2)) {                                   \
00595       safe_assign(var_addr, index,                                      \
00596                   (CPtr) makeattv(hreg),var_addr_arraysz);              \
00597       num_heap_term_vars++;                                             \
00598       new_heap_free(hreg);                                              \
00599       push_addr(hreg);                                                  \
00600       hreg++;                                                           \
00601       rec_macro_make_heap_term(dummy_addr);                             \
00602     }                                                                   \
00603     ret_val = (Cell) var_addr[index];                                   \
00604   }                                                                     \
00605   break;                                                                \
00606   case XSB_STRING:                                                      \
00607   case XSB_INT:                                                         \
00608   case XSB_FLOAT:                                                       \
00609     ret_val = xtemp2;                                                   \
00610     break;                                                              \
00611   case XSB_LIST:                                                        \
00612     ret_val = (Cell) makelist(hreg) ;                                   \
00613     hreg += 2;                                                          \
00614     push_addr(hreg-1);                                                  \
00615     push_addr(hreg-2);                                                  \
00616     rec_macro_make_heap_term(dummy_addr);                               \
00617     break;                                                              \
00618   case XSB_STRUCT:                                                      \
00619     ret_val = (Cell) makecs(hreg);                                      \
00620     xtemp2 = (Cell) DecodeTrieFunctor(xtemp2);                          \
00621     *hreg = xtemp2;                                                     \
00622     mArity = (int) get_arity((Psc) xtemp2);                             \
00623     for (mj= mArity; mj >= 1; mj--) {                                   \
00624       push_addr(hreg+mj);                                               \
00625     }                                                                   \
00626     hreg += mArity;                                                     \
00627     hreg++;                                                             \
00628     rec_macro_make_heap_term(dummy_addr);                               \
00629     break;                                                              \
00630   default:                                                              \
00631     xsb_abort("Bad tag in macro_make_heap_term");                       \
00632     return;                                                             \
00633   }                                                                     \
00634   if (top_of_localstk < top_of_heap) xsb_abort("Heap overflow: should expand"); \
00635 }
00636 
00637 /*----------------------------------------------------------------------*/
00638 
00639 #define recvariant_trie(flag,TrieType) {                                \
00640   int  j;                                                               \
00641                                                                         \
00642   while (!pdlempty ) {                                                  \
00643     xtemp1 = (CPtr) pdlpop;                                             \
00644     XSB_CptrDeref(xtemp1);                                              \
00645     tag = cell_tag(xtemp1);                                             \
00646     switch (tag) {                                                      \
00647     case XSB_FREE:                                                      \
00648     case XSB_REF1:                                                      \
00649       if (! IsStandardizedVariable(xtemp1)) {                           \
00650         StandardizeAndTrailVariable(xtemp1,ctr);                        \
00651         item = EncodeNewTrieVar(ctr);                                   \
00652         one_node_chk_ins(flag, item, TrieType);                         \
00653         ctr++;                                                          \
00654       } else {                                                          \
00655         item = IndexOfStdVar(xtemp1);                                   \
00656         item = EncodeTrieVar(item);                                     \
00657         one_node_chk_ins(flag, item, TrieType);                         \
00658       }                                                                 \
00659       break;                                                            \
00660     case XSB_STRING:                                                    \
00661     case XSB_INT:                                                       \
00662     case XSB_FLOAT:                                                     \
00663       one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), TrieType);     \
00664       break;                                                            \
00665     case XSB_LIST:                                                      \
00666       one_node_chk_ins(flag, EncodeTrieList(xtemp1), TrieType);         \
00667       pdlpush(cell(clref_val(xtemp1)+1));                               \
00668       pdlpush(cell(clref_val(xtemp1)));                                 \
00669       break;                                                            \
00670     case XSB_STRUCT:                                                    \
00671       psc = (Psc) follow(cs_val(xtemp1));                               \
00672       item = makecs(psc);                                               \
00673       one_node_chk_ins(flag, item, TrieType);                           \
00674       for (j = get_arity(psc); j>=1 ; j--) {                            \
00675         pdlpush(cell(clref_val(xtemp1)+j));                             \
00676       }                                                                 \
00677       break;                                                            \
00678     case XSB_ATTV:                                                      \
00679       /* Now xtemp1 can only be the first occurrence of an attv */      \
00680       xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */        \
00681       StandardizeAndTrailVariable(xtemp1, ctr);                         \
00682       one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), INTERN_TRIE_TT);   \
00683       attv_ctr++; ctr++;                                                \
00684       pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */         \
00685       break;                                                            \
00686     default:                                                            \
00687       xsb_abort("Bad type tag in recvariant_trie...\n");                \
00688     }                                                                   \
00689   }                                                                     \
00690   resetpdl;                                                             \
00691 }
00692 
00693 /*----------------------------------------------------------------------*/
00694 
00695 /*
00696  * This is a special version of recvariant_trie(), and it is only used by 
00697  * variant_answer_search().  The only difference between this and
00698  * recvariant_trie() is that this version will save the answer
00699  * substitution factor into the heap (see the following lines):
00700  *
00701  *      bld_free(hreg);
00702  *      bind_ref(xtemp1, hreg);
00703  *      xtemp1 = hreg++;
00704  */
00705 
00706 #define recvariant_trie_ans_subsf(flag,TrieType) {                      \
00707   int  j;                                                               \
00708                                                                         \
00709   while (!pdlempty ) {                                                  \
00710     xtemp1 = (CPtr) pdlpop;                                             \
00711     XSB_CptrDeref(xtemp1);                                              \
00712     tag = cell_tag(xtemp1);                                             \
00713     switch (tag) {                                                      \
00714     case XSB_FREE:                                                      \
00715     case XSB_REF1:                                                      \
00716       if (! IsStandardizedVariable(xtemp1)){                            \
00717         bld_free(hreg);                                                 \
00718         bind_ref(xtemp1, hreg);                                         \
00719         xtemp1 = hreg++;                                                \
00720         StandardizeAndTrailVariable(xtemp1,ctr);                        \
00721         one_node_chk_ins(flag,EncodeNewTrieVar(ctr),TrieType);          \
00722         ctr++;                                                          \
00723       } else {                                                          \
00724         one_node_chk_ins(flag,                                          \
00725                          EncodeTrieVar(IndexOfStdVar(xtemp1)),          \
00726                          TrieType);                                     \
00727       }                                                                 \
00728       break;                                                            \
00729     case XSB_STRING:                                                    \
00730     case XSB_INT:                                                       \
00731     case XSB_FLOAT:                                                     \
00732       one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), TrieType);     \
00733       break;                                                            \
00734     case XSB_LIST:                                                      \
00735       one_node_chk_ins(flag, EncodeTrieList(xtemp1), TrieType);         \
00736       pdlpush(cell(clref_val(xtemp1)+1));                               \
00737       pdlpush(cell(clref_val(xtemp1)));                                 \
00738       break;                                                            \
00739     case XSB_STRUCT:                                                    \
00740       psc = (Psc) follow(cs_val(xtemp1));                               \
00741       item = makecs(psc);                                               \
00742       one_node_chk_ins(flag, item, TrieType);                           \
00743       for (j = get_arity(psc); j>=1 ; j--) {                            \
00744         pdlpush(cell(clref_val(xtemp1)+j));                             \
00745       }                                                                 \
00746       break;                                                            \
00747     case XSB_ATTV:                                                      \
00748       /* Now xtemp1 can only be the first occurrence of an attv */      \
00749       /* *(hreg++) = (Cell) xtemp1;     */                              \
00750       xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */        \
00751       StandardizeAndTrailVariable(xtemp1, ctr);                         \
00752       one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), TrieType);         \
00753       attv_ctr++; ctr++;                                                \
00754       pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */         \
00755       break;                                                            \
00756     default:                                                            \
00757       xsb_abort("Bad type tag in recvariant_trie_ans_subsf...\n");      \
00758     }                                                                   \
00759   }                                                                     \
00760   resetpdl;                                                             \
00761 }
00762 
00763 
00764 #include "term_psc_xsb_i.h"
00765 #include "ptoc_tag_xsb_i.h"
00766 
00767 
00768 /*
00769  * Called in SLG instruction `new_answer_dealloc', variant_answer_search()
00770  * checks if the answer has been returned before and, if not, inserts it
00771  * into the answer trie.  Here, `sf_size' is the number of variables in the
00772  * substitution factor of the called subgoal, `attv_num' is the number of
00773  * attributed variables in the call, `cptr' is the pointer to the
00774  * substitution factor, and `subgoal_ptr' is the subgoal frame of the
00775  * call.  At the end of this function, `flagptr' tells if the answer
00776  * has been returned before.
00777  *
00778  * The returned value of this function is the leaf of the answer trie.
00779  */
00780 
00781 BTNptr variant_answer_search(CTXTdeclc int sf_size, int attv_num, CPtr cptr,
00782                              VariantSF subgoal_ptr, xsbBool *flagptr) {
00783 
00784   Psc   psc;
00785   CPtr  xtemp1;
00786   int   i, j, flag = 1;
00787   Cell  tag = XSB_FREE, item, tmp_var;
00788   ALNptr answer_node;
00789   int ctr, attv_ctr;
00790   BTNptr Paren, *GNodePtrPtr;
00791 
00792   ans_chk_ins++; /* Counter (answers checked & inserted) */
00793 
00794   VarEnumerator_trail_top = (CPtr *)(& VarEnumerator_trail[0]) - 1;
00795   AnsVarCtr = 0;
00796   ctr = 0;
00797   if ( IsNULL(subg_ans_root_ptr(subgoal_ptr)) ) {
00798     Cell retSymbol;
00799     if ( sf_size > 0 )
00800       retSymbol = EncodeTriePSC(get_ret_psc(sf_size));
00801     else
00802       retSymbol = EncodeTrieConstant(makestring(get_ret_string()));
00803     subg_ans_root_ptr(subgoal_ptr) =
00804       newBasicAnswerTrie(CTXTc retSymbol, (CPtr) subgoal_ptr, 
00805                          BASIC_ANSWER_TRIE_TT);
00806   }
00807   Paren = subg_ans_root_ptr(subgoal_ptr);
00808   GNodePtrPtr = &BTN_Child(Paren);
00809 
00810   /* Documentation rewritten by TLS: 
00811    * To properly generate instructions for attributed variables, you
00812    * need to know which attributed variables are identical to those in
00813    * the call, and which represent new bindings to attributed or vanilla
00814    * variables.  The marking below binds binds the VAR part of the
00815    * attvs to an element of VarEnumerator[].  When the for() loop
00816    * dereferences these variables they can be recognized as pointing
00817    * into VarEnumerator, and a trie_xxx_val instruction will be
00818    * generated for them.  Other attvs will dereference elsewhere and
00819    * will generate a trie_xxx_attv instruction.  Note that in doing
00820    * this, attributes in the call will not need to be re-entered in
00821    * the table.
00822    * 
00823    * According to Bao's algorithm, in order for trie instructions for
00824    * completed tables to work for attvs, attvs in the call must be
00825    * traversed before the main loop and bound to elements of
00826    * varEnumerator so that the trie_xxx_val instructions can recognize
00827    * them and avoid interrupts.  As a result, both here and in the tabletry
00828    * setup for completed tables, the substitution factor is traversed
00829    * and the attvs set to the lower portion of varEnumerator.  To save
00830    * time, this is only done when there is at least one attv in 
00831    * the call (attv_num > 0).  ¹
00832    */
00833   if (attv_num > 0) {
00834     for (i = 0; i < sf_size; i++) {
00835       tmp_var = cell(cptr - i);
00836       if (isattv(tmp_var)) {
00837         xtemp1 = clref_val(tmp_var); /* the VAR part */
00838         if (xtemp1 == (CPtr) cell(xtemp1)) { /* this attv is not changed */
00839           StandardizeAndTrailVariable(xtemp1, ctr);
00840         }
00841         ctr++;
00842       }
00843     }
00844     /* now ctr should be equal to attv_num */
00845   }
00846   attv_ctr = attv_num;
00847 
00848   for (i = 0; i < sf_size; i++) {
00849     xtemp1 = (CPtr) (cptr - i); /* One element of VarsInCall.  It might
00850                                  * have been bound in the answer for
00851                                  * the call.
00852                                  */
00853     XSB_CptrDeref(xtemp1);
00854     tag = cell_tag(xtemp1);
00855     switch (tag) {
00856     case XSB_FREE: 
00857     case XSB_REF1:
00858       if (! IsStandardizedVariable(xtemp1)) {
00859         /*
00860          * Note that unlike variant_call_search(), vas() trails
00861          * variables (by using VarEnumerator_trail_top, rather than
00862          * full SLG-WAM trailing.  Thus, if this is the first
00863          * occurrence of this variable, then: 
00864          *
00865          *      StandardizeAndTrailVariable(xtemp1, ctr)
00866          *                      ||
00867          *      bld_ref(xtemp1, VarEnumerator[ctr]);
00868          *      *(++VarEnumerator_trail_top) = xtemp1
00869          *
00870          * By doing this, all the variables appearing in the answer
00871          * are bound to elements in VarEnumerator[], and each element
00872          * in VarEnumerator[] is a free variable itself.  vcs() was
00873          * able to avoid the trail because all variables were placed
00874          * on the substitution factor; variables encountered in an
00875          * answer substitution can be anywhere on the heap.  Also
00876          * note that this function uses the pdl stack rather than
00877          * reg_array, as does vsc().
00878          * The variables will be used in 
00879          * delay_chk_insert() (in function do_delay_stuff()).
00880          */
00881 
00882 #ifndef IGNORE_DELAYVAR
00883         bld_free(hreg); // make sure there is no pointer from heap to local stack.
00884         bind_ref(xtemp1, hreg);
00885         xtemp1 = hreg++;
00886 #endif
00887         StandardizeAndTrailVariable(xtemp1,ctr);
00888         item = EncodeNewTrieVar(ctr);
00889         one_node_chk_ins(flag, item, BASIC_ANSWER_TRIE_TT);
00890         ctr++;
00891       } else {
00892         item = IndexOfStdVar(xtemp1);
00893         item = EncodeTrieVar(item);
00894         one_node_chk_ins(flag, item, BASIC_ANSWER_TRIE_TT);
00895       }
00896       break;
00897     case XSB_STRING: 
00898     case XSB_INT:
00899     case XSB_FLOAT:
00900       one_node_chk_ins(flag, EncodeTrieConstant(xtemp1),
00901                        BASIC_ANSWER_TRIE_TT);
00902       break;
00903     case XSB_LIST:
00904       one_node_chk_ins(flag, EncodeTrieList(xtemp1), BASIC_ANSWER_TRIE_TT);
00905       pdlpush(cell(clref_val(xtemp1)+1));
00906       pdlpush(cell(clref_val(xtemp1)));
00907 #ifndef IGNORE_DELAYVAR
00908       recvariant_trie_ans_subsf(flag, BASIC_ANSWER_TRIE_TT);
00909 #else
00910       recvariant_trie(flag, BASIC_ANSWER_TRIE_TT);
00911 #endif 
00912       break;
00913     case XSB_STRUCT:
00914       psc = (Psc)follow(cs_val(xtemp1));
00915       item = makecs(psc);
00916       one_node_chk_ins(flag, item, BASIC_ANSWER_TRIE_TT);
00917       for (j = get_arity(psc); j >= 1 ; j--) {
00918         pdlpush(cell(clref_val(xtemp1)+j));
00919       }
00920 #ifndef IGNORE_DELAYVAR
00921       recvariant_trie_ans_subsf(flag, BASIC_ANSWER_TRIE_TT);
00922 #else
00923       recvariant_trie(flag, BASIC_ANSWER_TRIE_TT);
00924 #endif
00925       break;
00926     case XSB_ATTV:
00927       /* Now xtemp1 can only be the first occurrence of an attv */
00928       //      *(hreg++) = (Cell) xtemp1;
00929       xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
00930       /*
00931        * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
00932        * later occurrences of this attv will look like a regular variable
00933        * (after dereferencing).
00934        */
00935       StandardizeAndTrailVariable(xtemp1, ctr); 
00936       one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), BASIC_ANSWER_TRIE_TT);
00937       attv_ctr++; ctr++;
00938       pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */
00939 #ifndef IGNORE_DELAYVAR
00940       recvariant_trie_ans_subsf(flag, BASIC_ANSWER_TRIE_TT);
00941 #else
00942       recvariant_trie(flag, BASIC_ANSWER_TRIE_TT);
00943 #endif
00944       break;
00945     default:
00946       xsb_abort("Bad type tag in variant_answer_search()");
00947     }                                                       
00948   }
00949   resetpdl;                                                   
00950 
00951 #ifndef IGNORE_DELAYVAR
00952   /*
00953    * Put the substitution factor of the answer into a term ret/n (if 
00954    * the sf_size of the substitution factor is 0, then put integer 0
00955    * into cell ans_var_pos_reg).
00956    *
00957    * Notice that simple_table_undo_bindings in pre-1.9 version of XSB
00958    * has been removed here, because all the variable bindings of this
00959    * answer will be used in do_delay_stuff() immediatly after the
00960    * return of vas() when we build the delay list for this answer.
00961    */
00962   if (ctr == 0)
00963     bld_int(ans_var_pos_reg, 0);
00964   else  
00965     bld_functor(ans_var_pos_reg, get_ret_psc(ctr));
00966 #else /* IGNORE_DELAYVAR */
00967   undo_answer_bindings(CTXT);
00968 #endif
00969 
00970   /*
00971      * Save the number of variables in the answer, i.e. the sf_size of
00972      * the substitution factor of the answer, into `AnsVarCtr'.
00973      */
00974   AnsVarCtr = ctr;              
00975 
00976 #ifdef DEBUG_DELAYVAR
00977   xsb_dbgmsg((LOG_DEBUG,">>>> [V] AnsVarCtr = %d", AnsVarCtr));
00978 #endif
00979 
00980   /* if there is no term to insert, an ESCAPE node has to be created/found */
00981 
00982   if (sf_size == 0) {
00983     one_node_chk_ins(flag, ESCAPE_NODE_SYMBOL, BASIC_ANSWER_TRIE_TT);
00984     Instr(Paren) = trie_proceed;
00985   }
00986 
00987   /*
00988    *  If an insertion was performed, do some maintenance on the new leaf,
00989    *  and place the answer handle onto the answer list.
00990    */
00991   if ( flag == 0 ) {
00992     MakeLeafNode(Paren);
00993     TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
00994     ans_inserts++;
00995 
00996     New_ALN(subgoal_ptr,answer_node,Paren,NULL);
00997     SF_AppendNewAnswer(subgoal_ptr,answer_node);
00998   }
00999 
01000   *flagptr = flag;      
01001   return Paren;
01002 }
01003 
01004 /*
01005  * undo_answer_bindings() has the same functionality of
01006  * simple_table_undo_bindings.  It is called just after do_delay_stuff(),
01007  * and do_delay_stuff() is called after variant_answer_search (in
01008  * new_answer_dealloc)
01009  *
01010  * In XSB 1.8.1, simple_table_undo_bindings is called in
01011  * variant_answer_search().  But to handle variables in delay list in
01012  * do_delay_stuff() , we need the variable binding information got from
01013  * variant_answer_search().  So we have to take simple_table_undo_bindings
01014  * out of variant_answer_search() and call it after do_delay_stuff() is
01015  * done.
01016  */
01017 
01018 void undo_answer_bindings(CTXTdecl) {
01019   simple_table_undo_bindings;
01020 }
01021 
01022 /*
01023  * Function delay_chk_insert() is called only from intern_delay_element()
01024  * to create the delay trie for the corresponding delay element.  This
01025  * delay trie contains the substitution factor of the answer to the subgoal
01026  * call of this delay element.  Its leaf node will be saved as a field,
01027  * de_subs_fact_leaf, in the delay element.
01028  *
01029  * This function is closely related to variant_answer_search(), because it
01030  * uses the value of AnsVarCtr that is set in variant_answer_search().  The
01031  * body of this function is almost the same as the core part of
01032  * variant_answer_search(), except that `ctr', the counter of the variables
01033  * in the answer, starts from AnsVarCtr.  Initially, before the first delay
01034  * element in the delay list of a subgoal (say p/2), is interned, AnsVarCtr
01035  * is the number of variables in the answer for p/2 and it was set in
01036  * variant_answer_search() when this answer was returned.  Then, AnsVarCtr
01037  * will be dynamically increased as more and more delay elements for p/2
01038  * are interned.
01039  *
01040  * After variant_answer_search() is finished, VarEnumerator[] contains the
01041  * variables in the head of the corresponding clause for p/2.  When we call
01042  * delay_chk_insert() to intern the delay list for p/2, VarEnumerator[]
01043  * will be used again to bind the variables that appear in the body.
01044  * Because we have to check if a variable in a delay element of p/2 is
01045  * already in the head, the old bindings of variables to VarEnumerator[]
01046  * are still needed.  So undo_answer_bindings has to be delayed.
01047  *
01048  * In the arguments, `arity' is the arity of the the answer substitution
01049  * factor, `cptr' points to the first field of term ret/n (the answer
01050  * substitution factor), `hook' is a pointer to a location where the top of
01051  * this delay trie will become anchored.  Since these delay "tries" only
01052  * occur as single paths, there is currently no need for a root node.
01053  */
01054  
01055 BTNptr delay_chk_insert(CTXTdeclc int arity, CPtr cptr, CPtr *hook)
01056 {
01057     Psc  psc;
01058     Cell item;
01059     CPtr xtemp1;
01060     int  i, j, tag = XSB_FREE, flag = 1;
01061     int ctr, attv_ctr;
01062     BTNptr Paren, *GNodePtrPtr;
01063  
01064 #ifdef DEBUG_DELAYVAR
01065     xsb_dbgmsg((LOG_DEBUG,">>>> start delay_chk_insert()"));
01066 #endif
01067 
01068     Paren = NULL;
01069     GNodePtrPtr = (BTNptr *) hook;
01070 
01071     ctr = AnsVarCtr;
01072 
01073 #ifdef DEBUG_DELAYVAR
01074     xsb_dbgmsg((LOG_DEBUG,">>>> [D1] AnsVarCtr = %d", AnsVarCtr));
01075 #endif
01076 
01077     for (i = 0; i<arity; i++) {
01078       /*
01079        * Notice: the direction of saving the variables in substitution
01080        * factors has been changed.  Because Prasad saves the substitution
01081        * factors in CP stack (--VarPosReg), but I save them in heap
01082        * (hreg++).  So (cptr - i) is changed to (cptr + i) in the
01083        * following line.
01084        */
01085       xtemp1 = (CPtr) (cptr + i);
01086       xsb_dbgmsg((LOG_BD, "arg[%d] =  %x ",i, xtemp1));
01087       XSB_CptrDeref(xtemp1);
01088       dbg_printterm(LOG_BD,stddbg,(unsigned int)xtemp1,25);
01089       xsb_dbgmsg((LOG_BD, "\n"));
01090       tag = cell_tag(xtemp1);
01091       switch (tag) {
01092       case XSB_FREE:
01093       case XSB_REF1:
01094         if (! IsStandardizedVariable(xtemp1)) {
01095           StandardizeAndTrailVariable(xtemp1,ctr);
01096           one_node_chk_ins(flag,EncodeNewTrieVar(ctr),
01097                            DELAY_TRIE_TT);
01098           ctr++;
01099         }
01100         else {
01101           one_node_chk_ins(flag,
01102                            EncodeTrieVar(IndexOfStdVar(xtemp1)),
01103                            DELAY_TRIE_TT);
01104         }
01105         break;
01106       case XSB_STRING: 
01107       case XSB_INT:
01108       case XSB_FLOAT:
01109         one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), DELAY_TRIE_TT);
01110         break;
01111       case XSB_LIST:
01112         one_node_chk_ins(flag, EncodeTrieList(xtemp1), DELAY_TRIE_TT);
01113         pdlpush(cell(clref_val(xtemp1)+1));
01114         pdlpush(cell(clref_val(xtemp1)));
01115         recvariant_trie(flag,DELAY_TRIE_TT);
01116         break;
01117       case XSB_STRUCT:
01118         one_node_chk_ins(flag, makecs(follow(cs_val(xtemp1))),DELAY_TRIE_TT);
01119         for (j = get_arity((Psc)follow(cs_val(xtemp1))); j >= 1 ; j--) {
01120           pdlpush(cell(clref_val(xtemp1)+j));
01121         }
01122         recvariant_trie(flag,DELAY_TRIE_TT);
01123         break;
01124       case XSB_ATTV:
01125         //      /* Now xtemp1 can only be the first occurrence of an attv */
01126         //      *(hreg++) = (Cell) xtemp1;
01127         xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
01128         /*
01129          * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
01130          * later occurrences of this attv will look like a regular variable
01131          * (after dereferencing).
01132          */
01133         if (! IsStandardizedVariable(xtemp1)) {
01134           StandardizeAndTrailVariable(xtemp1, ctr);     
01135           one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), DELAY_TRIE_TT);
01136           ctr++; attv_ctr++;
01137         }
01138         else {
01139           one_node_chk_ins(flag,
01140                            EncodeTrieVar(IndexOfStdVar(xtemp1)),
01141                            DELAY_TRIE_TT);
01142         }
01143         pdlpush(cell(xtemp1+1));        /* the ATTR part of the attv */
01144         recvariant_trie(flag, DELAY_TRIE_TT);
01145         break;
01146       default:
01147           xsb_abort("Bad type tag in delay_chk_insert()\n");
01148         }
01149     }
01150     resetpdl;  
01151     AnsVarCtr = ctr;
01152 
01153 #ifdef DEBUG_DELAYVAR
01154     xsb_dbgmsg((LOG_DEBUG,">>>> [D2] AnsVarCtr = %d", AnsVarCtr));
01155 #endif
01156 
01157     /*
01158      *  If an insertion was performed, do some maintenance on the new leaf.
01159      */
01160     if ( flag == 0 ) {
01161       MakeLeafNode(Paren);
01162       TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
01163     }
01164  
01165     xsb_dbgmsg((LOG_BD, "----------------------------- Exit\n"));
01166     return Paren;
01167 }
01168 
01169 /*----------------------------------------------------------------------*/
01170 /* for each variable in call, builds its binding on the heap.           */
01171 /*----------------------------------------------------------------------*/
01172 
01173 /*
01174  * Expects that the path in the trie -- to which the variables (stored in
01175  * the vector `cptr') are to be unified -- has been pushed onto the
01176  * termstack.
01177  */
01178 static void load_solution_from_trie(CTXTdeclc int arity, CPtr cptr)
01179 {
01180    int i;
01181    CPtr xtemp1, Dummy_Addr;
01182    Cell returned_val, xtemp2;
01183 
01184    for (i=0; i<arity; i++) {
01185      xtemp1 = (CPtr) (cptr-i);
01186      XSB_CptrDeref(xtemp1);
01187      macro_make_heap_term(xtemp1,returned_val,Dummy_Addr);
01188      if (xtemp1 != (CPtr)returned_val) {
01189        if (isref(xtemp1)) {     /* a regular variable */
01190          dbind_ref(xtemp1,returned_val);
01191        }
01192        else {                   /* an XSB_ATTV */
01193          /* Bind the variable part of xtemp1 to returned_val */
01194          add_interrupt(CTXTc cell(((CPtr)dec_addr(xtemp1) + 1)), returned_val); 
01195          dbind_ref((CPtr) dec_addr(xtemp1), returned_val);
01196        }
01197      }
01198    }
01199    resetpdl;
01200 }
01201 
01202 /*----------------------------------------------------------------------*/
01203 
01204 /*
01205  * Unifies the path in the interned trie identified by `Leaf' with the term
01206  * `term'.  It appears that `term' is expected to be an unbound variable.
01207  * Also, `Root' does not appear to be used.
01208  */
01209 static void bottomupunify(CTXTdeclc Cell term, BTNptr Root, BTNptr Leaf)
01210 {
01211   CPtr Dummy_Addr;
01212   Cell returned_val, xtemp2;
01213   CPtr gen;
01214   int  i;
01215 
01216   num_heap_term_vars = 0;     
01217   follow_par_chain(CTXTc Leaf);
01218   XSB_Deref(term);
01219   gen = (CPtr) term;
01220   macro_make_heap_term(gen,returned_val,Dummy_Addr);
01221   bld_ref(gen,returned_val);
01222 
01223   for(i = 0; i < num_heap_term_vars; i++){
01224     var_regs[i] = var_addr[i];
01225   }
01226   /*
01227    * global_num_vars is needed by get_lastnode_cs_retskel() (see
01228    * trie_interned/4 in intern.P).
01229    *
01230    * Last_Nod_Sav is also needed by get_lastnode_cs_retskel().  We can
01231    * set it to Leaf.
01232    */
01233   global_num_vars = num_vars_in_var_regs = num_heap_term_vars - 1;
01234   Last_Nod_Sav = Leaf;
01235 }
01236 
01237 /*----------------------------------------------------------------------*/
01238 
01239 /*
01240  *  Used with tries created via the builtin trie_intern.
01241  */
01242 
01243 #ifndef MULTI_THREAD
01244   extern  BTNptr *Set_ArrayPtr;
01245 #endif
01246 
01247 xsbBool bottom_up_unify(CTXTdecl)
01248 {
01249   Cell    term;
01250   BTNptr root;
01251   BTNptr leaf;
01252   int     rootidx;
01253 
01254   leaf = (BTNptr) ptoc_int(CTXTc 3);   
01255   if( IsDeletedNode(leaf) )
01256     return FALSE;
01257 
01258   term    = ptoc_tag(CTXTc 1);
01259   rootidx = ptoc_int(CTXTc 2);
01260   root    = Set_ArrayPtr[rootidx];  
01261   bottomupunify(CTXTc term, root, leaf);
01262   return TRUE;
01263 }
01264 
01265 /*----------------------------------------------------------------------*/
01266 
01267 /*
01268  * `TriePtr' is a leaf in the answer trie, and `cptr' is a vector of
01269  * variables for receiving the substitution.
01270  */
01271 void load_solution_trie(CTXTdeclc int arity, int attv_num, CPtr cptr, BTNptr TriePtr)
01272 {
01273   CPtr xtemp;
01274   
01275   num_heap_term_vars = 0;
01276   if (arity > 0) {
01277     /* Initialize var_addr[] as the attvs in the call. */
01278     if (attv_num > 0) {
01279       for (xtemp = cptr; xtemp > cptr - arity; xtemp--) {
01280         if (isattv(cell(xtemp))) {
01281           //      var_addr[num_heap_term_vars] = (CPtr) cell(xtemp);
01282           safe_assign(var_addr,num_heap_term_vars,(CPtr) cell(xtemp),var_addr_arraysz);
01283           num_heap_term_vars++;
01284         }
01285       }
01286     }
01287     follow_par_chain(CTXTc TriePtr);
01288     load_solution_from_trie(CTXTc arity,cptr);
01289   }
01290 }
01291 
01292 /*----------------------------------------------------------------------*/
01293 
01294 void load_delay_trie(CTXTdeclc int arity, CPtr cptr, BTNptr TriePtr)
01295 {
01296    if (arity) {
01297      follow_par_chain(CTXTc TriePtr);
01298      load_solution_from_trie(CTXTc arity,cptr);
01299    }
01300 }
01301  
01302 /*----------------------------------------------------------------------*/
01303 
01304 #define recvariant_call(flag,TrieType,xtemp1) {                         \
01305   int  j;                                                               \
01306                                                                         \
01307   while (!pdlempty) {                                                   \
01308     xtemp1 = (CPtr) pdlpop;                                             \
01309     XSB_CptrDeref(xtemp1);                                              \
01310     switch(tag = cell_tag(xtemp1)) {                                    \
01311     case XSB_FREE:                                                      \
01312     case XSB_REF1:                                                      \
01313       if (! IsStandardizedVariable(xtemp1)) {                           \
01314         *(--VarPosReg) = (Cell) xtemp1;                                 \
01315         StandardizeVariable(xtemp1,ctr);                                \
01316         one_node_chk_ins(flag,EncodeNewTrieVar(ctr),TrieType);          \
01317         ctr++;                                                          \
01318       } else{                                                           \
01319         one_node_chk_ins(flag, EncodeTrieVar(IndexOfStdVar(xtemp1)),    \
01320                          TrieType);                                     \
01321       }                                                                 \
01322       break;                                                            \
01323     case XSB_STRING:                                                    \
01324     case XSB_INT:                                                       \
01325     case XSB_FLOAT:                                                     \
01326       one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), TrieType);     \
01327       break;                                                            \
01328     case XSB_LIST:                                                      \
01329       one_node_chk_ins(flag, EncodeTrieList(xtemp1), TrieType);         \
01330       pdlpush( cell(clref_val(xtemp1)+1) );                             \
01331       pdlpush( cell(clref_val(xtemp1)) );                               \
01332       break;                                                            \
01333     case XSB_STRUCT:                                                    \
01334       psc = (Psc) follow(cs_val(xtemp1));                               \
01335       item = makecs(psc);                                               \
01336       one_node_chk_ins(flag, item, TrieType);                           \
01337       for (j=get_arity(psc); j>=1; j--) {                               \
01338         pdlpush(cell(clref_val(xtemp1)+j));                             \
01339       }                                                                 \
01340       break;                                                            \
01341     case XSB_ATTV:                                                      \
01342       /* Now xtemp1 can only be the first occurrence of an attv */      \
01343       *(--VarPosReg) = (Cell) xtemp1;                                   \
01344       xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */        \
01345       StandardizeVariable(xtemp1, ctr);                                 \
01346       one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), TrieType);         \
01347       attv_ctr++; ctr++;                                                \
01348       pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */         \
01349       break;                                                            \
01350     default:                                                            \
01351       xsb_abort("Bad type tag in recvariant_call...\n");                \
01352     }                                                                   \
01353   }                                                                     \
01354   resetpdl;                                                             \
01355 }
01356 
01357 /*----------------------------------------------------------------------*/
01358 
01359 /* TLS gloss: 
01360  * 
01361  * To me it seems this function is written in an overly general way.
01362  * I dont see a real need to encapsulate all of its input and output
01363  * as it is only called once, in tabletry.  What's lost is: 
01364  * cptr is simply a pointer to the reg_array, cptr = reg+1 
01365  * VarPosReg is top_of_cpstack.  This can cause confusion since later in
01366  * table_call_search (which calls this function) the substitution
01367  * factor is copied to the heap.
01368  * 
01369  * In addition, the manner in which attributed variables are handled
01370  * gives rise to some special features in the code.  When adding an
01371  * answer, it is not straightforward to determine whether a binding
01372  * to a substitution factor was made in the original call or as part
01373  * of program clause resolution.  variant_call_search() creates a
01374  * substitution factor on the choice point stack.  Immediately after
01375  * variant_call_search() returns, table_call_search() will copy the
01376  * substitution factor from the choice point stack to the heap.  It
01377  * can then be determined whether attributed variables are old or new
01378  * by comparing the value of a cell in the choice point stack to the
01379  * corresponding value in the heap.  If they are the same, the
01380  * attributed variable was in the call, and a trie_xxx_val
01381  * instruction can be used.  If not, other actions must be taken --
01382  * generating either a trie_xxx_val or trie_xxx_attv.
01383  * 
01384  * While most of this happens in later functions, certain
01385  * features of vcs() can be accounted for by these later actions.
01386  * For instance, each local variable is copied to the heap in vcs().
01387  * This is to avoid pointers from the heap substitution factor (once
01388  * it is created) into the local stack.
01389  *
01390  */
01391 
01392 /*
01393  * Searches/inserts a subgoal call structure into a subgoal call trie.
01394  * During search/insertion, the variables of the subgoal call are
01395  * pushed on top of the CP stack (through VarPosReg), along with the #
01396  * of variables that were pushed.  This forms the substitution factor.
01397  * Prolog variables are standardized during this process to recognize
01398  * multiple (nonlinear) occurences.  They must be reset to an unbound
01399  * state before termination.
01400  * 
01401  * Important variables: 
01402  * Paren - to be set to point to inserted term's leaf
01403  * VarPosReg - pointer to top of CPS; place to put the substitution factor
01404  *    in high-to-low memory format.
01405  * GNodePtrPtr - Points to the parent-internal-structure's
01406  *    "child" or "NODE_link" field.  It's a place to anchor any newly
01407  *    created NODEs.
01408  * ctr - contains the number of distinct variables found
01409  *    in the call.
01410  * Pay careful attention to the expected argument vector accepted by this
01411  * function.  It actually points one Cell *before* the term vector!  Notice
01412  * the treatment of "cptr" as these terms are inspected.
01413  */
01414 
01415 void variant_call_search(CTXTdeclc TabledCallInfo *call_info,
01416                          CallLookupResults *results)
01417 {
01418   Psc  psc;
01419   CPtr call_arg;
01420   int  arity, i, j, flag = 1;
01421   Cell tag = XSB_FREE, item;
01422   CPtr cptr, VarPosReg, tVarPosReg;
01423   int ctr, attv_ctr;
01424   BTNptr Paren, *GNodePtrPtr;
01425 
01426   subg_chk_ins++;
01427   Paren = TIF_CallTrie(CallInfo_TableInfo(*call_info));
01428   GNodePtrPtr = &BTN_Child(Paren);
01429   arity = CallInfo_CallArity(*call_info);
01430   /* cptr is set to point to the reg_array */
01431   cptr = CallInfo_Arguments(*call_info);
01432   tVarPosReg = VarPosReg = CallInfo_VarVectorLoc(*call_info);
01433   ctr = attv_ctr = 0;
01434 
01435   for (i = 0; i < arity; i++) {
01436     xsb_dbgmsg((LOG_DEBUG,">>>> (argument %d)",i+1));
01437     call_arg = (CPtr) (cptr + i);            /* Note! */
01438     XSB_CptrDeref(call_arg);
01439     tag = cell_tag(call_arg);
01440     switch (tag) {
01441     case XSB_FREE:
01442     case XSB_REF1:
01443       if (! IsStandardizedVariable(call_arg)) {
01444 
01445         /* Call_arg is now a dereferenced register value.  If it
01446          * points to a local variable, make both the local variable
01447          * and call_arg point to a new free variable in the heap.
01448          * As noted in the documentation at the start of this function,
01449          * this is to support attributed variables in tabling.   
01450          */
01451 
01452         xsb_dbgmsg((LOG_DEBUG,"   new variable ctr = %d)",ctr));
01453 
01454         if (top_of_localstk <= call_arg &&
01455             call_arg <= (CPtr) glstack.high - 1) {
01456           bld_free(hreg);
01457           bind_ref(call_arg, hreg);
01458           call_arg = hreg++;
01459         }
01460         /*
01461          * Make VarPosReg, which points to the top of the choice point
01462          * stack, point to call_arg, which now points a free variable in the
01463          * heap.  Make that heap free variable point to the
01464          * VarEnumerator array, via StandardizeVariable.   The
01465          * VarEnumerator array contains variables that point to
01466          * themselves (init'd in init_trie_aux_areas()).  vcs() does
01467          * not change bindings in the VarEnumerator array -- it just
01468          * changes bindings of heap variables that point into it.
01469          */
01470         *(--VarPosReg) = (Cell) call_arg;       
01471         StandardizeVariable(call_arg,ctr);
01472         one_node_chk_ins(flag,EncodeNewTrieVar(ctr),
01473                          CALL_TRIE_TT);
01474         ctr++;
01475       } else {
01476         one_node_chk_ins(flag,EncodeTrieVar(IndexOfStdVar(call_arg)),CALL_TRIE_TT);
01477       }
01478       break;
01479     case XSB_STRING:
01480     case XSB_INT:
01481     case XSB_FLOAT:
01482       one_node_chk_ins(flag, EncodeTrieConstant(call_arg), CALL_TRIE_TT);
01483       break;
01484     case XSB_LIST:
01485       one_node_chk_ins(flag, EncodeTrieList(call_arg), CALL_TRIE_TT);
01486       pdlpush(cell(clref_val(call_arg)+1));
01487       pdlpush(cell(clref_val(call_arg)));
01488       recvariant_call(flag,CALL_TRIE_TT,call_arg);
01489       break;
01490     case XSB_STRUCT:
01491       psc = (Psc)follow(cs_val(call_arg));
01492       item = makecs(psc);
01493       one_node_chk_ins(flag, item, CALL_TRIE_TT);
01494       for (j=get_arity(psc); j>=1 ; j--) {
01495         pdlpush(cell(clref_val(call_arg)+j));
01496       }
01497       recvariant_call(flag,CALL_TRIE_TT,call_arg);
01498       break;
01499     case XSB_ATTV:
01500       /* call_arg is derefed register value pointing to heap.  Make
01501          the subst factor CP-stack pointer, VarPosReg, point to it. */
01502       *(--VarPosReg) = (Cell) call_arg;
01503       xsb_dbgmsg((LOG_TRIE,"In VSC: attv deref'd reg %x; val: %x into AT: %x",
01504                  call_arg,clref_val(call_arg),VarPosReg));
01505       call_arg = clref_val(call_arg); /* the VAR part of the attv */
01506       /*
01507        * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
01508        * later occurrences of this attv will look like a regular variable
01509        * (after dereferencing).
01510        */
01511       StandardizeVariable(call_arg, ctr);       
01512       one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), CALL_TRIE_TT);
01513       attv_ctr++; ctr++;
01514       pdlpush(cell(call_arg+1));        /* the ATTR part of the attv */
01515       recvariant_call(flag, CALL_TRIE_TT, call_arg);
01516       break;
01517     default:
01518       xsb_abort("Bad type tag in variant_call_search...\n");
01519     }
01520   }
01521   resetpdl;
01522     
01523   if (arity == 0) {
01524     one_node_chk_ins(flag, ESCAPE_NODE_SYMBOL, CALL_TRIE_TT);
01525     Instr(Paren) = trie_proceed;
01526   }
01527 
01528   /*
01529    *  If an insertion was performed, do some maintenance on the new leaf.
01530    */
01531   if ( flag == 0 ) {
01532     subg_inserts++;
01533     MakeLeafNode(Paren);
01534     TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
01535   }
01536 
01537   cell(--VarPosReg) = makeint(attv_ctr << 16 | ctr);
01538   /* 
01539    * "Untrail" any variable that used to point to VarEnumerator.  For
01540    * variables, note that *VarPosReg is the address of a cell in the
01541    * heap.  To reset that variable, we make that address free.
01542    * Similarly, *VarPosReg may contain the (encoded) address of an
01543    * attv on the heap.  In this case, we make the VAR part of that
01544    * attv point to itself.  The actual value in VarPosReg (i.e. the
01545    * of a substitution factor) doesn't change in either case.
01546    */     
01547   while (--tVarPosReg > VarPosReg) {
01548     if (isref(*tVarPosReg))     /* a regular variable */
01549       ResetStandardizedVariable(*tVarPosReg);
01550     else                        /* an XSB_ATTV */
01551       ResetStandardizedVariable(clref_val(*tVarPosReg));
01552   }
01553 
01554   CallLUR_Leaf(*results) = Paren;
01555   CallLUR_Subsumer(*results) = CallTrieLeaf_GetSF(Paren);
01556   CallLUR_VariantFound(*results) = flag;
01557   CallLUR_VarVector(*results) = VarPosReg;
01558   return;
01559 }
01560 
01561 /*----------------------------------------------------------------------*/
01562 
01563 static void remove_calls_and_returns(CTXTdeclc VariantSF CallStrPtr)
01564 {
01565   ALNptr pALN;
01566 
01567   /* Delete the call entry
01568      --------------------- */
01569   SET_TRIE_ALLOCATION_TYPE_SF(CallStrPtr);
01570   delete_branch(CTXTc subg_leaf_ptr(CallStrPtr),
01571                 &TIF_CallTrie(subg_tif_ptr(CallStrPtr)));
01572 
01573   /* Delete its answers
01574      ------------------ */
01575   for ( pALN = subg_answers(CallStrPtr);  IsNonNULL(pALN);
01576         pALN = ALN_Next(pALN) )
01577     delete_branch(CTXTc ALN_Answer(pALN), &subg_ans_root_ptr(CallStrPtr));
01578 
01579   /* Delete the table entry
01580      ---------------------- */
01581   free_answer_list(CallStrPtr);
01582   FreeProducerSF(CallStrPtr);
01583 }
01584 
01585 void remove_incomplete_tries(CTXTdeclc CPtr bottom_parameter)
01586 {
01587   xsbBool warned = FALSE;
01588   VariantSF CallStrPtr;
01589 
01590   while (openreg < bottom_parameter) {
01591     CallStrPtr = (VariantSF)compl_subgoal_ptr(openreg);
01592     if (!is_completed(CallStrPtr)) {
01593       if (warned == FALSE) {
01594         xsb_mesg("Removing incomplete tables...");
01595         //      check_table_cut = FALSE;  /* permit cuts over tables */
01596         warned = TRUE;
01597       }
01598       remove_calls_and_returns(CTXTc CallStrPtr);
01599     }
01600     openreg += COMPLFRAMESIZE;
01601   }
01602 }
01603 
01604 /*----------------------------------------------------------------------*/
01605 
01606 /*
01607  * For creating interned tries via buitin "trie_intern".
01608  */
01609 
01610 BTNptr whole_term_chk_ins(CTXTdeclc Cell term, BTNptr *hook, int *flagptr)
01611 {
01612     Psc  psc;
01613     CPtr xtemp1;
01614     int  j, flag = 1;
01615     Cell tag = XSB_FREE, item;
01616     int ctr, attv_ctr;
01617     BTNptr Paren, *GNodePtrPtr;
01618 
01619 
01620     if ( IsNULL(*hook) )
01621       *hook = newBasicTrie(CTXTc EncodeTriePSC(get_intern_psc()),INTERN_TRIE_TT);
01622     Paren = *hook;
01623     GNodePtrPtr = &BTN_Child(Paren);
01624 
01625     xtemp1 = (CPtr) term;
01626     XSB_CptrDeref(xtemp1);
01627     tag = cell_tag(xtemp1);
01628 
01629     VarEnumerator_trail_top = (CPtr *)(& VarEnumerator_trail[0]) - 1;
01630     ctr = attv_ctr = 0;
01631 
01632     switch (tag) {
01633     case XSB_FREE: 
01634     case XSB_REF1:
01635       if (! IsStandardizedVariable(xtemp1)) {
01636         StandardizeAndTrailVariable(xtemp1,ctr);
01637         one_node_chk_ins(flag,EncodeNewTrieVar(ctr),
01638                          INTERN_TRIE_TT);
01639         ctr++;
01640       } else {
01641         one_node_chk_ins(flag,
01642                          EncodeTrieVar(IndexOfStdVar(xtemp1)),
01643                          INTERN_TRIE_TT);
01644       }
01645       break;
01646     case XSB_STRING: 
01647     case XSB_INT:
01648     case XSB_FLOAT:
01649       one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), INTERN_TRIE_TT);
01650       break;
01651     case XSB_LIST:
01652       one_node_chk_ins(flag, EncodeTrieList(xtemp1), INTERN_TRIE_TT);
01653       pdlpush(cell(clref_val(xtemp1)+1));
01654       pdlpush(cell(clref_val(xtemp1)));
01655       recvariant_trie(flag,INTERN_TRIE_TT);
01656       break;
01657     case XSB_STRUCT:
01658       one_node_chk_ins(flag, makecs(follow(cs_val(xtemp1))),INTERN_TRIE_TT);
01659       for (j = get_arity((Psc)follow(cs_val(xtemp1))); j >= 1 ; j--) {
01660         pdlpush(cell(clref_val(xtemp1)+j));
01661       }
01662       recvariant_trie(flag,INTERN_TRIE_TT);
01663       break;
01664     case XSB_ATTV:
01665       /* Now xtemp1 can only be the first occurrence of an attv */
01666       xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
01667       /*
01668        * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
01669        * later occurrences of this attv will look like a regular variable
01670        * (after dereferencing).
01671        */
01672       StandardizeAndTrailVariable(xtemp1, ctr); 
01673       one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), INTERN_TRIE_TT);
01674       attv_ctr++; ctr++;
01675       pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */
01676       recvariant_trie(flag, INTERN_TRIE_TT);
01677       break;
01678     default:
01679       xsb_abort("Bad type tag in whole_term_check_ins()");
01680     }
01681 
01682     /*
01683      *  If an insertion was performed, do some maintenance on the new leaf.
01684      */
01685     if ( flag == 0 ) {
01686       MakeLeafNode(Paren);
01687       TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
01688     }
01689 
01690     /*
01691      * var_regs[] is used to construct the last argument of trie_intern/5
01692      * (Skel).  This is done in construct_ret(), which is called in
01693      * get_lastnode_cs_retskel().
01694      */
01695     for (j = 0; j < ctr; j++) var_regs[j] = VarEnumerator_trail[j];
01696     /*
01697      * Both global_num_vars and Last_Nod_Sav are needed by
01698      * get_lastnode_cs_retskel() (see trie_intern/5 in intern.P).
01699      */
01700     global_num_vars = num_vars_in_var_regs = ctr - 1;
01701     Last_Nod_Sav = Paren;
01702     simple_table_undo_bindings;
01703 
01704     /* if node was deleted, then return 0 to indicate that the insertion took
01705        place conceptually (even if not physically */
01706     if (IsDeletedNode(Paren)) {
01707       *flagptr = 0;
01708       undelete_branch(Paren);
01709     } else
01710       *flagptr = flag;
01711 
01712     return(Paren);
01713 }
01714 
01715 /*----------------------------------------------------------------------*/
01716 /* one_term_chk_ins(termptr,hook,flag)                                  */
01717 /*----------------------------------------------------------------------*/
01718 
01719 /*
01720  * For creating asserted tries with builtin "trie_assert".
01721  */
01722 
01723 BTNptr one_term_chk_ins(CTXTdeclc CPtr termptr, BTNptr root, int *flagptr)
01724 {
01725   int  arity;
01726   CPtr cptr;
01727   CPtr xtemp1;
01728   int  i, j, flag = 1;
01729   Cell tag = XSB_FREE, item;
01730   Psc  psc;
01731   int ctr, attv_ctr;
01732   BTNptr Paren, *GNodePtrPtr;
01733 
01734   psc = term_psc((prolog_term)termptr);
01735   arity = get_arity(psc);
01736   cptr = (CPtr)cs_val(termptr);
01737 
01738   VarEnumerator_trail_top = (CPtr *)(& VarEnumerator_trail[0]) - 1;
01739   ctr = attv_ctr = 0;
01740   /*
01741    * The value of `Paren' effects the "body" of the trie: nodes which
01742    * are created the first level down get this value in their parent
01743    * field.  This could be a problem when deleting trie paths, as this
01744    * root needs to persist beyond the life of its body.
01745    */
01746   Paren = root;
01747   GNodePtrPtr = &BTN_Child(root);
01748   for (i = 1; i<=arity; i++) {
01749     xtemp1 = (CPtr) (cptr + i);
01750     XSB_CptrDeref(xtemp1);
01751     tag = cell_tag(xtemp1);
01752     switch (tag) {
01753     case XSB_FREE: 
01754     case XSB_REF1:
01755       if (! IsStandardizedVariable(xtemp1)) {
01756         StandardizeAndTrailVariable(xtemp1,ctr);
01757         one_node_chk_ins(flag, EncodeNewTrieVar(ctr),
01758                          ASSERT_TRIE_TT);
01759         ctr++;
01760       } else {
01761         one_node_chk_ins(flag,
01762                          EncodeTrieVar(IndexOfStdVar(xtemp1)),
01763                          ASSERT_TRIE_TT);
01764       }
01765       break;
01766     case XSB_STRING: 
01767     case XSB_INT:
01768     case XSB_FLOAT:
01769       one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), ASSERT_TRIE_TT);
01770       break;
01771     case XSB_LIST:
01772       one_node_chk_ins(flag, EncodeTrieList(xtemp1), ASSERT_TRIE_TT);
01773       pdlpush(cell(clref_val(xtemp1)+1));
01774       pdlpush(cell(clref_val(xtemp1)));
01775       recvariant_trie(flag,ASSERT_TRIE_TT);
01776       break;
01777     case XSB_STRUCT:
01778       psc = (Psc) follow(cs_val(xtemp1));
01779       one_node_chk_ins(flag, makecs(psc),ASSERT_TRIE_TT);
01780       for (j = get_arity(psc); j >= 1 ; j--) {
01781         pdlpush(cell(clref_val(xtemp1)+j));
01782       }
01783       recvariant_trie(flag,ASSERT_TRIE_TT);
01784       break;
01785     case XSB_ATTV:
01786       /* Now xtemp1 can only be the first occurrence of an attv */
01787       xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
01788       /*
01789        * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
01790        * later occurrences of this attv will look like a regular variable
01791        * (after dereferencing).
01792        */
01793       StandardizeAndTrailVariable(xtemp1, ctr); 
01794       one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), ASSERT_TRIE_TT);
01795       attv_ctr++; ctr++;
01796       pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */
01797       recvariant_trie(flag, ASSERT_TRIE_TT);
01798       break;
01799     default:
01800       xsb_abort("Bad type tag in one_term_check_ins()");
01801     }
01802   }                
01803   resetpdl;                                                   
01804 
01805   simple_table_undo_bindings;
01806 
01807   /* if there is no term to insert, an ESCAPE node has to be created/found */
01808 
01809   if (arity == 0) {
01810     one_node_chk_ins(flag, ESCAPE_NODE_SYMBOL, ASSERT_TRIE_TT);
01811     Instr(Paren) = trie_proceed;
01812   }
01813 
01814   /*
01815    *  If an insertion was performed, do some maintenance on the new leaf.
01816    */
01817   if ( flag == 0 ) {
01818     MakeLeafNode(Paren);
01819     TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
01820   }
01821 
01822   *flagptr = flag;      
01823   return(Paren);
01824 }
01825 
01826 /*----------------------------------------------------------------------*/
01827 
01828 /*
01829  * This is builtin #150: TRIE_GET_RETURN
01830  */
01831 
01832 byte *trie_get_returns(CTXTdeclc VariantSF sf, Cell retTerm) {
01833 
01834   BTNptr ans_root_ptr;
01835   Cell retSymbol;
01836 #ifdef MULTI_THREAD_RWL
01837    CPtr tbreg;
01838 #ifdef SLG_GC
01839    CPtr old_cptop;
01840 #endif
01841 #endif
01842 
01843 
01844 #ifdef DEBUG_DELAYVAR
01845   xsb_dbgmsg((LOG_DEBUG,">>>> (at the beginning of trie_get_returns"));
01846   xsb_dbgmsg((LOG_DEBUG,">>>> num_vars_in_var_regs = %d)", num_vars_in_var_regs));
01847 #endif
01848 
01849   if ( IsProperlySubsumed(sf) )
01850     ans_root_ptr = subg_ans_root_ptr(conssf_producer(sf));
01851   else
01852     ans_root_ptr = subg_ans_root_ptr(sf);
01853   if ( IsNULL(ans_root_ptr) )
01854     return (byte *)&fail_inst;
01855 
01856   if ( isconstr(retTerm) )
01857     retSymbol = EncodeTrieFunctor(retTerm);  /* ret/n rep as XSB_STRUCT */
01858   else
01859     retSymbol = retTerm;   /* ret/0 would be represented as a XSB_STRING */
01860   if ( retSymbol != BTN_Symbol(ans_root_ptr) )
01861     return (byte *)&fail_inst;
01862 
01863   num_vars_in_var_regs = -1;
01864   if ( isconstr(retTerm) ) {
01865     int i, arity;
01866     CPtr cptr;
01867 
01868     arity = get_arity(get_str_psc(retTerm));
01869     /* Initialize var_regs[] as the attvs in the call. */
01870     for (i = 0, cptr = clref_val(retTerm) + 1;  i < arity;  i++, cptr++) {
01871       if (isattv(cell(cptr)))
01872         var_regs[++num_vars_in_var_regs] = (CPtr) cell(cptr);
01873     }
01874     /* now num_vars_in_var_regs should be attv_num - 1 */
01875 
01876     reg_arrayptr = reg_array -1;
01877     for (i = arity, cptr = clref_val(retTerm);  i >= 1;  i--) {
01878       pushreg(cell(cptr+i));
01879     }
01880   }
01881 #ifdef DEBUG_DELAYVAR
01882   xsb_dbgmsg((LOG_DEBUG,">>>> The end of trie_get_returns ==> go to answer trie"));
01883 #endif
01884   delay_it = 0;  /* Don't delay the answer. */
01885 #ifdef MULTI_THREAD_RWL
01886 /* save choice point for trie_unlock instruction */
01887        save_find_locx(ereg);
01888        tbreg = top_of_cpstack;
01889 #ifdef SLG_GC
01890        old_cptop = tbreg;
01891 #endif
01892        save_choicepoint(tbreg,ereg,(byte *)&trie_fail_unlock_inst,breg);
01893 #ifdef SLG_GC
01894        cp_prevtop(tbreg) = old_cptop;
01895 #endif
01896        breg = tbreg;
01897        hbreg = hreg;
01898 #endif
01899   return (byte *)ans_root_ptr;
01900 }
01901 
01902 /*----------------------------------------------------------------------*/
01903 
01904 byte * trie_get_calls(CTXTdecl)
01905 {
01906    Cell call_term;
01907    Psc psc_ptr;
01908    TIFptr tip_ptr;
01909    BTNptr call_trie_root;
01910    CPtr cptr;
01911    int i;
01912 #ifdef MULTI_THREAD_RWL
01913    CPtr tbreg;
01914 #ifdef SLG_GC
01915    CPtr old_cptop;
01916 #endif
01917 #endif
01918 
01919    call_term = ptoc_tag(CTXTc 1);
01920    if ((psc_ptr = term_psc(call_term)) != NULL) {
01921      tip_ptr = get_tip(CTXTc psc_ptr);
01922      if (tip_ptr == NULL) {
01923        xsb_abort("get_calls/3 called with non-tabled predicate");
01924        return (byte *)&fail_inst;
01925      }
01926      call_trie_root = TIF_CallTrie(tip_ptr);
01927      if (call_trie_root == NULL)
01928        return (byte *)&fail_inst;
01929      else {
01930        cptr = (CPtr)cs_val(call_term);
01931        reg_arrayptr = reg_array-1;
01932        num_vars_in_var_regs = -1;
01933        for (i = get_arity(psc_ptr); i>=1; i--) {
01934 #ifdef DEBUG_DELAYVAR
01935          xsb_dbgmsg((LOG_DEBUG,">>>> push one cell"));
01936 #endif
01937          pushreg(cell(cptr+i));
01938        }
01939 #ifdef MULTI_THREAD_RWL
01940 /* save choice point for trie_unlock instruction */
01941        save_find_locx(ereg);
01942        tbreg = top_of_cpstack;
01943 #ifdef SLG_GC
01944        old_cptop = tbreg;
01945 #endif
01946        save_choicepoint(tbreg,ereg,(byte *)&trie_fail_unlock_inst,breg);
01947 #ifdef SLG_GC
01948        cp_prevtop(tbreg) = old_cptop;
01949 #endif
01950        breg = tbreg;
01951        hbreg = hreg;
01952 #endif
01953 
01954        return (byte *)call_trie_root;
01955      }
01956    }
01957    else
01958      return (byte *)&fail_inst;
01959 }
01960 
01961 /*----------------------------------------------------------------------*/
01962 
01963 /*
01964  * This function is changed from get_lastnode_and_retskel().  It is the
01965  * body of *inline* builtin GET_LASTNODE_CS_RETSKEL(LastNode, CallStr,
01966  * RetSkel). [1/9/1999]
01967  *
01968  * This function is called immediately after using the trie intructions
01969  * to traverse one branch of the call or answer trie.  A side-effect of
01970  * executing these instructions is that the leaf node of the branch is
01971  * left in a global variable "Last_Nod_Sav".  One reason for writing it
01972  * so is that it is important that the construction of the return
01973  * skeleton is an operation that cannot be interrupted by garbage
01974  * collection.
01975  *
01976  * In case we just traversed the Call Trie of a subsumptive predicate,
01977  * and the call we just unified with is subsumed, then the answer
01978  * template (i.e., the return) must be reconstructed based on the
01979  * original call, the argument "callTerm" below, and the subsuming call
01980  * in the table.  Otherwise, we return the variables placed in
01981  * "var_regs[]" during the embedded-trie-code walk.
01982  */
01983 Cell get_lastnode_cs_retskel(CTXTdeclc Cell callTerm) {
01984 
01985   int arity;
01986   Cell *vector;
01987 
01988   arity = global_num_vars + 1;
01989   vector = (Cell *)var_regs;
01990   if ( IsInCallTrie(Last_Nod_Sav) ) {
01991     VariantSF sf = CallTrieLeaf_GetSF(Last_Nod_Sav);
01992     if ( IsProperlySubsumed(sf) ) {
01993       construct_answer_template(CTXTc callTerm, conssf_producer(sf),
01994                                 (Cell *)var_regs);
01995       arity = (int)var_regs[0];
01996       vector = (Cell *)&var_regs[1];
01997     }
01998   }
01999   return ( build_ret_term(CTXTc arity, vector) );
02000 }
02001 
02002 /*----------------------------------------------------------------------*/
02003 /* creates an empty (dummy) answer.                                     */
02004 /*----------------------------------------------------------------------*/
02005 
02006 ALNptr empty_return(CTXTdeclc VariantSF subgoal)
02007 {
02008     ALNptr i;
02009   
02010     /* Used only in one context hence this abuse */
02011     New_ALN(subgoal,i,&dummy_ans_node,NULL);
02012     return i;
02013 }
02014 
02015 /*----------------------------------------------------------------------*/

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