~burner/xsb/debianized-xsb

« back to all changes in this revision

Viewing changes to emu/tries.c

  • Committer: Michael R. Head
  • Date: 2006-09-06 22:11:55 UTC
  • Revision ID: burner@n23-20060906221155-7e398d23438a7ee4
Add the files from the 3.0.1 release package

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* File:      tries.c
 
2
** Author(s): Prasad Rao, David S. Warren, Kostis Sagonas,
 
3
**            Juliana Freire, Baoqiu Cui
 
4
** Contact:   xsb-contact@cs.sunysb.edu
 
5
** 
 
6
** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
 
7
** Copyright (C) ECRC, Germany, 1990
 
8
** 
 
9
** XSB is free software; you can redistribute it and/or modify it under the
 
10
** terms of the GNU Library General Public License as published by the Free
 
11
** Software Foundation; either version 2 of the License, or (at your option)
 
12
** any later version.
 
13
** 
 
14
** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
 
15
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
16
** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
 
17
** more details.
 
18
** 
 
19
** You should have received a copy of the GNU Library General Public License
 
20
** along with XSB; if not, write to the Free Software Foundation,
 
21
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
22
**
 
23
** $Id: tries.c,v 1.87 2006/05/22 14:53:44 dwarren Exp $
 
24
** 
 
25
*/
 
26
 
 
27
 
 
28
#include "xsb_config.h"
 
29
#include "xsb_debug.h"
 
30
 
 
31
#include <stdio.h>
 
32
#include <stdlib.h>
 
33
 
 
34
/* Special debug includes */
 
35
#include "debugs/debug_tries.h"
 
36
 
 
37
#include "auxlry.h"
 
38
#include "cell_xsb.h"
 
39
#include "inst_xsb.h"
 
40
#include "psc_xsb.h"
 
41
#include "heap_xsb.h"
 
42
#include "flags_xsb.h"
 
43
#include "deref.h"
 
44
#include "memory_xsb.h"
 
45
#include "register.h"
 
46
#include "binding.h"
 
47
#include "trie_internals.h"
 
48
#include "macro_xsb.h"
 
49
#include "choice.h"
 
50
#include "cinterf.h"
 
51
#include "error_xsb.h"
 
52
#include "tr_utils.h"
 
53
#include "rw_lock.h"
 
54
#include "thread_xsb.h"
 
55
#include "debug_xsb.h"
 
56
#include "subp.h"
 
57
 
 
58
/*----------------------------------------------------------------------*/
 
59
/* The following variables are used in other parts of the system        */
 
60
/*----------------------------------------------------------------------*/
 
61
 
 
62
long subg_chk_ins, subg_inserts, ans_chk_ins, ans_inserts; /* statistics */
 
63
 
 
64
#ifndef MULTI_THREAD
 
65
int  num_heap_term_vars;
 
66
CPtr *var_addr;
 
67
int  var_addr_arraysz;
 
68
Cell VarEnumerator[NUM_TRIEVARS];
 
69
Cell TrieVarBindings[NUM_TRIEVARS];
 
70
#endif
 
71
 
 
72
/* xsbBool check_table_cut = TRUE;  flag for close_open_tables to turn off
 
73
                                    cut-over-table check */
 
74
 
 
75
/*
 
76
 * global_num_vars is a new variable to save the value of variable
 
77
 * num_vars_in_var_regs temporarily.
 
78
 */
 
79
#ifndef MULTI_THREAD
 
80
int global_num_vars;
 
81
#endif
 
82
 
 
83
/*
 
84
 * Array VarEnumerator_trail[] is used to trail the variable bindings when we
 
85
 * copy terms into tries.  The variables trailed using VarEnumerator_trail are
 
86
 * those that are bound to elements in VarEnumerator[].
 
87
 */
 
88
#ifndef MULTI_THREAD
 
89
static CPtr VarEnumerator_trail[NUM_TRIEVARS];
 
90
static CPtr *VarEnumerator_trail_top;
 
91
#endif
 
92
 
 
93
 
 
94
char *trie_node_type_table[] = {"interior_nt","hashed_interior_nt","leaf_nt",
 
95
                           "hashed_leaf_nt","hash_header_nt","undefined",
 
96
                           "undefined","undefined","trie_root_nt"};
 
97
 
 
98
char *trie_trie_type_table[] = {"call_trie_tt","basic_answer_trie_tt",
 
99
                                "ts_answer_trie_tt","delay_trie_tt",
 
100
                                "assert_trie_tt","intern_trie_tt"
 
101
};
 
102
 
 
103
/*----------------------------------------------------------------------*/
 
104
/* Safe assignment -- can be generalized by type.
 
105
   CPtr can be abstracted out */
 
106
#define safe_assign(ArrayNam,Index,Value,ArraySz) {\
 
107
   if (Index >= ArraySz) {\
 
108
     trie_expand_array(CPtr,ArrayNam,ArraySz,Index,"var_addr");\
 
109
   }\
 
110
   ArrayNam[Index] = Value;\
 
111
}
 
112
 
 
113
/*----------------------------------------------------------------------*/
 
114
/*****************Addr Stack************* 
 
115
 
 
116
 TLS 08/05: The addr_stack and term_stack (below) are used by
 
117
 answer_return.  to copy information out of a trie and into a ret/n
 
118
 structure.  Its also used by table predicates to get delay lists.
 
119
 
 
120
 */
 
121
 
 
122
#ifndef MULTI_THREAD
 
123
static int addr_stack_pointer = 0;
 
124
static CPtr *Addr_Stack;
 
125
static int addr_stack_size    = DEFAULT_ARRAYSIZ;
 
126
#endif
 
127
 
 
128
#define pop_addr Addr_Stack[--addr_stack_pointer]
 
129
#define push_addr(X) {\
 
130
    if (addr_stack_pointer == addr_stack_size) {\
 
131
       trie_expand_array(CPtr, Addr_Stack ,addr_stack_size,0,"Addr_Stack");\
 
132
    }\
 
133
    Addr_Stack[addr_stack_pointer++] = ((CPtr) X);\
 
134
}
 
135
 
 
136
/*----------------------------------------------------------------------*/
 
137
/*****************Term Stack*************/
 
138
#ifndef MULTI_THREAD
 
139
static int  term_stackptr = -1;
 
140
static Cell *term_stack;
 
141
static long term_stacksize = DEFAULT_ARRAYSIZ;
 
142
#endif
 
143
 
 
144
#define pop_term term_stack[term_stackptr--]
 
145
#define push_term(T) {\
 
146
    if (term_stackptr+1 == term_stacksize) {\
 
147
       trie_expand_array(Cell,term_stack,term_stacksize,0,"term_stack");\
 
148
    }\
 
149
    term_stack[++term_stackptr] = ((Cell) T);\
 
150
}
 
151
 
 
152
/*----------------------------------------------------------------------*/
 
153
/*********Simpler trails ****************/
 
154
 
 
155
#define simple_table_undo_bindings              \
 
156
    while (VarEnumerator_trail_top >= VarEnumerator_trail) {    \
 
157
        untrail(*VarEnumerator_trail_top);              \
 
158
        VarEnumerator_trail_top--;                      \
 
159
    }   
 
160
 
 
161
#define StandardizeAndTrailVariable(addr,n)     \
 
162
   StandardizeVariable(addr,n);                 \
 
163
    *(++VarEnumerator_trail_top) = addr;
 
164
                
 
165
/*----------------------------------------------------------------------*/
 
166
/* Variables used only in this file                                     */
 
167
/*----------------------------------------------------------------------*/
 
168
 
 
169
static BasicTrieNode dummy_ans_node = {{0,1,0,0},NULL,NULL,NULL,0};
 
170
 
 
171
#ifndef MULTI_THREAD
 
172
static int AnsVarCtr;
 
173
#endif
 
174
 
 
175
/*----------------------------------------------------------------------*/
 
176
 
 
177
/*
 
178
 *          T R I E   S T R U C T U R E   M A N A G E M E N T
 
179
 *          =================================================
 
180
 */
 
181
char *TrieSMNameTable[] = {"Basic Trie Node (Private)",
 
182
                   "Basic Trie Hash Table (Private)"};
 
183
 
 
184
/* For Call and Answer Tries
 
185
   ------------------------- */
 
186
 
 
187
Structure_Manager smTableBTN  = SM_InitDecl(BasicTrieNode, BTNs_PER_BLOCK,
 
188
                                            "Basic Trie Node");
 
189
Structure_Manager smTableBTHT = SM_InitDecl(BasicTrieHT, BTHTs_PER_BLOCK,
 
190
                                            "Basic Trie Hash Table");
 
191
 
 
192
/* For Assert & Intern Tries
 
193
   ------------------------- */
 
194
Structure_Manager smAssertBTN  = SM_InitDecl(BasicTrieNode, BTNs_PER_BLOCK,
 
195
                                             "Basic Trie Node");
 
196
Structure_Manager smAssertBTHT = SM_InitDecl(BasicTrieHT, BTHTs_PER_BLOCK,
 
197
                                             "Basic Trie Hash Table");
 
198
 
 
199
/* Maintains Current Structure Space
 
200
   --------------------------------- */
 
201
 
 
202
/* MT engine uses both shared and private structure managers,
 
203
   sequential engine doesn't.  In addition, in MT engine, all
 
204
   subsumptive tables are private, thus use subsumptive_smBTN/BTHT for
 
205
   structure managers common to both variant and private tables. */
 
206
 
 
207
#ifndef MULTI_THREAD
 
208
Structure_Manager smTSTN      = SM_InitDecl(TS_TrieNode, TSTNs_PER_BLOCK,
 
209
                                            "Time-Stamped Trie Node");
 
210
Structure_Manager smTSTHT     = SM_InitDecl(TST_HashTable, TSTHTs_PER_BLOCK,
 
211
                                            "Time-Stamped Trie Hash Table");
 
212
Structure_Manager smTSIN      = SM_InitDecl(TS_IndexNode, TSINs_PER_BLOCK,
 
213
                                            "Time-Stamp Indexing Node");
 
214
 
 
215
Structure_Manager *smBTN = &smTableBTN;
 
216
Structure_Manager *smBTHT = &smTableBTHT;
 
217
 
 
218
#endif
 
219
 
 
220
 
 
221
/*----------------------------------------------------------------------*/
 
222
 
 
223
void init_trie_aux_areas(CTXTdecl)
 
224
{
 
225
  int i;
 
226
 
 
227
  /* TLS: commented these out to catch private/shared bugs more
 
228
     quickly */
 
229
#ifndef MULTI_THREAD
 
230
  smBTN = &smTableBTN;
 
231
  smBTHT = &smTableBTHT;
 
232
#endif
 
233
 
 
234
  addr_stack_size = 0;
 
235
  Addr_Stack = NULL;
 
236
  addr_stack_pointer = 0;
 
237
 
 
238
  term_stacksize = 0;
 
239
  term_stack = NULL;
 
240
  term_stackptr = -1;
 
241
 
 
242
  var_addr_arraysz = 0;
 
243
  var_addr = NULL;
 
244
 
 
245
  reg_array = NULL;
 
246
  reg_array_size = 0;
 
247
  reg_arrayptr = reg_array -1;
 
248
 
 
249
  for (i = 0; i < NUM_TRIEVARS; i++)
 
250
    VarEnumerator[i] = (Cell) & (VarEnumerator[i]);
 
251
}
 
252
 
 
253
void free_trie_aux_areas(CTXTdecl)
 
254
{
 
255
  mem_dealloc(term_stack,term_stacksize,TABLE_SPACE);
 
256
  mem_dealloc(var_addr,var_addr_arraysz,TABLE_SPACE);
 
257
  mem_dealloc(Addr_Stack,addr_stack_size,TABLE_SPACE);
 
258
  mem_dealloc(reg_array,reg_array_size,TABLE_SPACE);
 
259
}
 
260
 
 
261
/*-------------------------------------------------------------------------*/
 
262
 
 
263
BTNptr new_btn(CTXTdeclc int trie_t, int node_t, Cell symbol, BTNptr parent,
 
264
               BTNptr sibling) {
 
265
 
 
266
  void *btn;
 
267
 
 
268
#ifdef MULTI_THREAD  
 
269
  if (threads_current_sm == PRIVATE_SM) {
 
270
    SM_AllocateStruct(*smBTN,btn);
 
271
  } else {
 
272
    SM_AllocateSharedStruct(*smBTN,btn);
 
273
    }
 
274
#else
 
275
  SM_AllocateStruct(*smBTN,btn);
 
276
#endif
 
277
  TN_Init(((BTNptr)btn),trie_t,node_t,symbol,parent,sibling);
 
278
  return (BTNptr)btn;
 
279
}
 
280
 
 
281
/*-------------------------------------------------------------------------*/
 
282
 
 
283
TSTNptr new_tstn(CTXTdeclc int trie_t, int node_t, Cell symbol, TSTNptr parent,
 
284
                TSTNptr sibling) {
 
285
 
 
286
  void * tstn;
 
287
 
 
288
  SM_AllocateStruct(smTSTN,tstn);
 
289
  TN_Init(((TSTNptr)tstn),trie_t,node_t,symbol,parent,sibling);
 
290
  TSTN_TimeStamp(((TSTNptr)tstn)) = TSTN_DEFAULT_TIMESTAMP;
 
291
  return (TSTNptr)tstn;
 
292
}
 
293
 
 
294
/*-------------------------------------------------------------------------*/
 
295
 
 
296
/*
 
297
 * Creates a root node for a given type of trie.
 
298
 */
 
299
 
 
300
BTNptr newBasicTrie(CTXTdeclc Cell symbol, int trie_type) {
 
301
 
 
302
  BTNptr pRoot;
 
303
 
 
304
  New_BTN( pRoot, trie_type, TRIE_ROOT_NT, symbol, NULL, NULL );
 
305
  return pRoot;
 
306
}
 
307
 
 
308
/*-------------------------------------------------------------------------*/
 
309
 
 
310
/*
 
311
 * Creates a root node for a given type of trie.  Differs from above in that
 
312
 * the parent is intended to be set to the subgoal frame.
 
313
 */
 
314
 
 
315
BTNptr newBasicAnswerTrie(CTXTdeclc Cell symbol, CPtr Paren, int trie_type) {
 
316
 
 
317
  BTNptr pRoot;
 
318
 
 
319
  New_BTN( pRoot, trie_type, TRIE_ROOT_NT, symbol, Paren, NULL );
 
320
  return pRoot;
 
321
}
 
322
 
 
323
/*----------------------------------------------------------------------*/
 
324
 
 
325
/* Used by one_node_chk_ins only. */
 
326
#define IsInsibling(wherefrom,count,Found,item,TrieType)                \
 
327
{                                                                       \
 
328
  LocalNodePtr = wherefrom;                                             \
 
329
  while (LocalNodePtr && (BTN_Symbol(LocalNodePtr) != item)) {          \
 
330
    LocalNodePtr = BTN_Sibling(LocalNodePtr);                           \
 
331
    count++;                                                            \
 
332
  }                                                                     \
 
333
  if ( IsNULL(LocalNodePtr) ) {                                         \
 
334
    Found = 0;                                                          \
 
335
    New_BTN(LocalNodePtr,TrieType,INTERIOR_NT,item,Paren,wherefrom);    \
 
336
    count++;                                                            \
 
337
    wherefrom = LocalNodePtr;  /* hook the new node into the trie */    \
 
338
  }                                                                     \
 
339
  Paren = LocalNodePtr;                                                 \
 
340
}
 
341
 
 
342
 
 
343
/*
 
344
 *  Insert/find a single symbol in the trie structure 1-level beneath a
 
345
 *  parent NODE, pointed to by `Paren', whose child link field is
 
346
 *  pointed to by 'GNodePtrPtr'.  (If 'Paren' is NULL, then we are most
 
347
 *  likely searching beneath some other structure, like the TIP, and
 
348
 *  'GNodePtrPtr' points to its "trie root" field.)  If the symbol
 
349
 *  cannot be found, create a NODE for this symbol and make it the child
 
350
 *  of `Paren' by setting the field that 'GNodePtrPtr' points to to this
 
351
 *  new NODE.  Upon exiting this macro, 'Paren' is set to point to the
 
352
 *  node containing this symbol and 'GNodePtrPtr' gets the address of
 
353
 *  this nodes' Child field.
 
354
 *
 
355
 *  Algorithm:
 
356
 *  ---------
 
357
 *  If the parent has no children, then create a node for the symbol
 
358
 *  and link it to the parent and vice versa.  Set the `Found' flag to
 
359
 *  indicate that a new node was necessary.
 
360
 *
 
361
 *  Otherwise, if the parent utilizes a hash structure for maintaining
 
362
 *  its children, check to see if there is enough room for one more
 
363
 *  entry.  If not, then expand the hash structure.  Search for the
 
364
 *  node containing the symbol in question, inserting it if it is not
 
365
 *  found.  Signify through `Found' the result of this action.
 
366
 *
 
367
 *  Otherwise, look for the symbol in a normal chain of children
 
368
 *  beneath the parent.  If it is not found, then insert it and check
 
369
 *  to see if the chain has now become too long; if so, then create a
 
370
 *  hash structure for the parent's children.  Signify through `Found'
 
371
 *  the result of this action.
 
372
 *
 
373
 *  Prepare for the next insertion/lookup by changing the `hook' to
 
374
 *  that of the child pointer field of the node which contains the
 
375
 *  just-processed symbol.
 
376
 */
 
377
 
 
378
#define one_node_chk_ins(Found,item,TrieType) {                         \
 
379
                                                                        \
 
380
   int count = 0;                                                       \
 
381
   BTNptr LocalNodePtr;                                                 \
 
382
                                                                        \
 
383
   TRIE_W_LOCK();                                                       \
 
384
   if ( IsNULL(*GNodePtrPtr) ) {                                        \
 
385
     New_BTN(LocalNodePtr,TrieType,INTERIOR_NT,item,Paren,NULL);        \
 
386
     *GNodePtrPtr = Paren = LocalNodePtr;                               \
 
387
     Found = 0;                                                         \
 
388
   }                                                                    \
 
389
   else if ( IsHashHeader(*GNodePtrPtr) ) {                             \
 
390
     BTHTptr ht = (BTHTptr)*GNodePtrPtr;                                \
 
391
     GNodePtrPtr = CalculateBucketForSymbol(ht,item);                   \
 
392
     IsInsibling(*GNodePtrPtr,count,Found,item,TrieType);               \
 
393
     if (!Found) {                                                      \
 
394
       MakeHashedNode(LocalNodePtr);                                    \
 
395
       BTHT_NumContents(ht)++;                                          \
 
396
       TrieHT_ExpansionCheck(ht,count);                                 \
 
397
     }                                                                  \
 
398
   }                                                                    \
 
399
   else {                                                               \
 
400
     BTNptr pParent = Paren;                                            \
 
401
     IsInsibling(*GNodePtrPtr,count,Found,item,TrieType);               \
 
402
     if (IsLongSiblingChain(count))                                     \
 
403
       /* used to pass in GNodePtrPtr (ptr to hook) */                  \
 
404
       hashify_children(CTXTc pParent,TrieType);                        \
 
405
   }                                                                    \
 
406
   GNodePtrPtr = &(BTN_Child(LocalNodePtr));                            \
 
407
   TRIE_W_UNLOCK();                                                     \
 
408
}
 
409
 
 
410
/*----------------------------------------------------------------------*/
 
411
 
 
412
/* Trie-HashTable maintenance routines.
 
413
   ------------------------------------
 
414
   parentHook is the address of a field in some structure (should now be
 
415
   another trie node as all tries now have roots) which points to a chain
 
416
   of trie nodes whose length has become "too long."
 
417
*/
 
418
 
 
419
void hashify_children(CTXTdeclc BTNptr parent, int trieType) {
 
420
 
 
421
  BTNptr children;              /* child list of the parent */
 
422
  BTNptr btn;                   /* current child for processing */
 
423
  BTHTptr ht;                   /* HT header struct */
 
424
  BTNptr *tablebase;            /* first bucket of allocated HT */
 
425
  unsigned long  hashseed;      /* needed for hashing of BTNs */
 
426
 
 
427
 
 
428
  New_BTHT(ht,trieType);
 
429
  children = BTN_Child(parent);
 
430
  BTN_SetHashHdr(parent,ht);
 
431
  tablebase = BTHT_BucketArray(ht);
 
432
  hashseed = BTHT_GetHashSeed(ht);
 
433
  for (btn = children;  IsNonNULL(btn);  btn = children) {
 
434
    children = BTN_Sibling(btn);
 
435
    TrieHT_InsertNode(tablebase, hashseed, btn);
 
436
    MakeHashedNode(btn);
 
437
  }
 
438
}
 
439
 
 
440
/*-------------------------------------------------------------------------*/
 
441
 
 
442
/*
 
443
 *  Expand the hash table pointed to by 'pHT'.  Note that we can do this
 
444
 *  in place by using realloc() and noticing that, since the hash tables
 
445
 *  and hashing function are based on powers of two, a node existing in
 
446
 *  a bucket will either remain in that bucket -- in the lower part of
 
447
 *  the new table -- or jump to a corresponding bucket in the upper half
 
448
 *  of the expanded table.  This function can serve for all types of
 
449
 *  tries since only fields contained in a Basic Trie Hash Table are
 
450
 *  manipulated.
 
451
 *
 
452
 *  As expansion is a method for reducing access time and is not a
 
453
 *  critical operation, if the table cannot be expanded at this time due
 
454
 *  to memory limitations, then simply return.  Otherwise, initialize
 
455
 *  the top half of the new area, and rehash each node in the buckets of
 
456
 *  the lower half of the table.
 
457
 */
 
458
 
 
459
 
 
460
void expand_trie_ht(BTHTptr pHT) {
 
461
 
 
462
  BTNptr *bucket_array;     /* base address of resized hash table */
 
463
  BTNptr *upper_buckets;    /* marker in the resized HT delimiting where the
 
464
                                newly allocated buckets begin */
 
465
 
 
466
  BTNptr *bucket;           /* for stepping through buckets of the HT */
 
467
 
 
468
  BTNptr curNode;           /* TSTN being processed */
 
469
  BTNptr nextNode;          /* rest of the TSTNs in a bucket */
 
470
 
 
471
  unsigned long  new_size;  /* double duty: new HT size, then hash mask */
 
472
 
 
473
 
 
474
  new_size = TrieHT_NewSize(pHT);
 
475
  bucket_array = (BTNptr *)mem_realloc( BTHT_BucketArray(pHT), BTHT_NumBuckets(pHT)*sizeof(void*),
 
476
                                     new_size * sizeof(BTNptr),TABLE_SPACE );
 
477
  if ( IsNULL(bucket_array) )
 
478
    return;
 
479
 
 
480
  upper_buckets = bucket_array + BTHT_NumBuckets(pHT);
 
481
  for (bucket = upper_buckets;  bucket < bucket_array + new_size;  bucket++)
 
482
    *bucket = NULL;
 
483
  BTHT_NumBuckets(pHT) = new_size;
 
484
  new_size--;     /* 'new_size' is now the hashing mask */
 
485
  BTHT_BucketArray(pHT) = bucket_array;
 
486
  for (bucket = bucket_array;  bucket < upper_buckets;  bucket++) {
 
487
    curNode = *bucket;
 
488
    *bucket = NULL;
 
489
    while ( IsNonNULL(curNode) ) {
 
490
      nextNode = TN_Sibling(curNode);
 
491
      TrieHT_InsertNode(bucket_array, new_size, curNode);
 
492
      curNode = nextNode;
 
493
    }
 
494
  }
 
495
}
 
496
 
 
497
/*----------------------------------------------------------------------*/
 
498
 
 
499
/*
 
500
 * Push the symbols along the path from the leaf to the root in a trie
 
501
 * onto the termstack.
 
502
 */
 
503
static void follow_par_chain(CTXTdeclc BTNptr pLeaf)
 
504
{
 
505
  term_stackptr = -1; /* Forcibly Empty term_stack */
 
506
  while ( IsNonNULL(pLeaf) && (! IsTrieRoot(pLeaf)) ) {
 
507
    push_term((BTN_Symbol(pLeaf)));
 
508
    pLeaf = BTN_Parent(pLeaf);
 
509
  }
 
510
}
 
511
 
 
512
/*----------------------------------------------------------------------*/
 
513
 
 
514
/*
 
515
 * Given a hook to an answer-list node, returns the answer contained in
 
516
 * that node and updates the hook to the next node in the chain.
 
517
 */
 
518
BTNptr get_next_trie_solution(ALNptr *NextPtrPtr)
 
519
{
 
520
  BTNptr TempPtr;
 
521
 
 
522
  TempPtr = ALN_Answer(*NextPtrPtr);
 
523
  *NextPtrPtr = ALN_Next(*NextPtrPtr);
 
524
  return(TempPtr);
 
525
}
 
526
 
 
527
/*----------------------------------------------------------------------*/
 
528
 
 
529
#define rec_macro_make_heap_term(Macro_addr) {                          \
 
530
  int rj,rArity;                                                        \
 
531
  while(addr_stack_pointer) {                                           \
 
532
    Macro_addr = (CPtr)pop_addr;                                        \
 
533
    xtemp2 = pop_term;                                                  \
 
534
    switch( TrieSymbolType(xtemp2) ) {                                  \
 
535
    case XSB_TrieVar: {                                                 \
 
536
      int index = DecodeTrieVar(xtemp2);                                \
 
537
      if (IsNewTrieVar(xtemp2)) {                                       \
 
538
        safe_assign(var_addr,index,Macro_addr,var_addr_arraysz);        \
 
539
        num_heap_term_vars++;                                           \
 
540
      }                                                                 \
 
541
      else if (IsNewTrieAttv(xtemp2)) {                                 \
 
542
        safe_assign(var_addr,index,                                     \
 
543
                    (CPtr) makeattv(hreg),var_addr_arraysz);            \
 
544
        num_heap_term_vars++;                                           \
 
545
        new_heap_free(hreg);                                            \
 
546
        push_addr(hreg);                                                \
 
547
        hreg++;                                                         \
 
548
      }                                                                 \
 
549
      *Macro_addr = (Cell) var_addr[index];                             \
 
550
    }                                                                   \
 
551
    break;                                                              \
 
552
    case XSB_STRING:                                                    \
 
553
    case XSB_INT:                                                       \
 
554
    case XSB_FLOAT:                                                     \
 
555
      *Macro_addr = xtemp2;                                             \
 
556
      break;                                                            \
 
557
    case XSB_LIST:                                                      \
 
558
      *Macro_addr = (Cell) makelist(hreg);                              \
 
559
      hreg += 2;                                                        \
 
560
      push_addr(hreg-1);                                                \
 
561
      push_addr(hreg-2);                                                \
 
562
      break;                                                            \
 
563
    case XSB_STRUCT:                                                    \
 
564
      *Macro_addr = (Cell) makecs(hreg);                                \
 
565
      xtemp2 = (Cell) DecodeTrieFunctor(xtemp2);                        \
 
566
      *hreg = xtemp2;                                                   \
 
567
      rArity = (int) get_arity((Psc) xtemp2);                           \
 
568
      for (rj= rArity; rj >= 1; rj --) {                                \
 
569
        push_addr(hreg+rj);                                             \
 
570
      }                                                                 \
 
571
      hreg += rArity;                                                   \
 
572
      hreg++;                                                           \
 
573
      break;                                                            \
 
574
    default:                                                            \
 
575
      xsb_abort("Bad tag in macro_make_heap_term");                     \
 
576
      return;                                                           \
 
577
    }                                                                   \
 
578
  }                                                                     \
 
579
  if (top_of_localstk < top_of_heap) xsb_abort("Heap overflow: should expand"); \
 
580
}
 
581
 
 
582
/*----------------------------------------------------------------------*/
 
583
 
 
584
#define macro_make_heap_term(ataddr,ret_val,dummy_addr) {               \
 
585
  int mArity,mj;                                                        \
 
586
  xtemp2 = pop_term;                                                    \
 
587
  switch( TrieSymbolType(xtemp2) ) {                                    \
 
588
  case XSB_TrieVar: {                                                   \
 
589
    int index = DecodeTrieVar(xtemp2);                                  \
 
590
    if (IsNewTrieVar(xtemp2)) { /* diff with CHAT - Kostis */           \
 
591
      safe_assign(var_addr,index,ataddr,var_addr_arraysz);              \
 
592
      num_heap_term_vars++;                                             \
 
593
    }                                                                   \
 
594
    else if (IsNewTrieAttv(xtemp2)) {                                   \
 
595
      safe_assign(var_addr, index,                                      \
 
596
                  (CPtr) makeattv(hreg),var_addr_arraysz);              \
 
597
      num_heap_term_vars++;                                             \
 
598
      new_heap_free(hreg);                                              \
 
599
      push_addr(hreg);                                                  \
 
600
      hreg++;                                                           \
 
601
      rec_macro_make_heap_term(dummy_addr);                             \
 
602
    }                                                                   \
 
603
    ret_val = (Cell) var_addr[index];                                   \
 
604
  }                                                                     \
 
605
  break;                                                                \
 
606
  case XSB_STRING:                                                      \
 
607
  case XSB_INT:                                                         \
 
608
  case XSB_FLOAT:                                                       \
 
609
    ret_val = xtemp2;                                                   \
 
610
    break;                                                              \
 
611
  case XSB_LIST:                                                        \
 
612
    ret_val = (Cell) makelist(hreg) ;                                   \
 
613
    hreg += 2;                                                          \
 
614
    push_addr(hreg-1);                                                  \
 
615
    push_addr(hreg-2);                                                  \
 
616
    rec_macro_make_heap_term(dummy_addr);                               \
 
617
    break;                                                              \
 
618
  case XSB_STRUCT:                                                      \
 
619
    ret_val = (Cell) makecs(hreg);                                      \
 
620
    xtemp2 = (Cell) DecodeTrieFunctor(xtemp2);                          \
 
621
    *hreg = xtemp2;                                                     \
 
622
    mArity = (int) get_arity((Psc) xtemp2);                             \
 
623
    for (mj= mArity; mj >= 1; mj--) {                                   \
 
624
      push_addr(hreg+mj);                                               \
 
625
    }                                                                   \
 
626
    hreg += mArity;                                                     \
 
627
    hreg++;                                                             \
 
628
    rec_macro_make_heap_term(dummy_addr);                               \
 
629
    break;                                                              \
 
630
  default:                                                              \
 
631
    xsb_abort("Bad tag in macro_make_heap_term");                       \
 
632
    return;                                                             \
 
633
  }                                                                     \
 
634
  if (top_of_localstk < top_of_heap) xsb_abort("Heap overflow: should expand"); \
 
635
}
 
636
 
 
637
/*----------------------------------------------------------------------*/
 
638
 
 
639
#define recvariant_trie(flag,TrieType) {                                \
 
640
  int  j;                                                               \
 
641
                                                                        \
 
642
  while (!pdlempty ) {                                                  \
 
643
    xtemp1 = (CPtr) pdlpop;                                             \
 
644
    XSB_CptrDeref(xtemp1);                                              \
 
645
    tag = cell_tag(xtemp1);                                             \
 
646
    switch (tag) {                                                      \
 
647
    case XSB_FREE:                                                      \
 
648
    case XSB_REF1:                                                      \
 
649
      if (! IsStandardizedVariable(xtemp1)) {                           \
 
650
        StandardizeAndTrailVariable(xtemp1,ctr);                        \
 
651
        item = EncodeNewTrieVar(ctr);                                   \
 
652
        one_node_chk_ins(flag, item, TrieType);                         \
 
653
        ctr++;                                                          \
 
654
      } else {                                                          \
 
655
        item = IndexOfStdVar(xtemp1);                                   \
 
656
        item = EncodeTrieVar(item);                                     \
 
657
        one_node_chk_ins(flag, item, TrieType);                         \
 
658
      }                                                                 \
 
659
      break;                                                            \
 
660
    case XSB_STRING:                                                    \
 
661
    case XSB_INT:                                                       \
 
662
    case XSB_FLOAT:                                                     \
 
663
      one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), TrieType);     \
 
664
      break;                                                            \
 
665
    case XSB_LIST:                                                      \
 
666
      one_node_chk_ins(flag, EncodeTrieList(xtemp1), TrieType);         \
 
667
      pdlpush(cell(clref_val(xtemp1)+1));                               \
 
668
      pdlpush(cell(clref_val(xtemp1)));                                 \
 
669
      break;                                                            \
 
670
    case XSB_STRUCT:                                                    \
 
671
      psc = (Psc) follow(cs_val(xtemp1));                               \
 
672
      item = makecs(psc);                                               \
 
673
      one_node_chk_ins(flag, item, TrieType);                           \
 
674
      for (j = get_arity(psc); j>=1 ; j--) {                            \
 
675
        pdlpush(cell(clref_val(xtemp1)+j));                             \
 
676
      }                                                                 \
 
677
      break;                                                            \
 
678
    case XSB_ATTV:                                                      \
 
679
      /* Now xtemp1 can only be the first occurrence of an attv */      \
 
680
      xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */        \
 
681
      StandardizeAndTrailVariable(xtemp1, ctr);                         \
 
682
      one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), INTERN_TRIE_TT);   \
 
683
      attv_ctr++; ctr++;                                                \
 
684
      pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */         \
 
685
      break;                                                            \
 
686
    default:                                                            \
 
687
      xsb_abort("Bad type tag in recvariant_trie...\n");                \
 
688
    }                                                                   \
 
689
  }                                                                     \
 
690
  resetpdl;                                                             \
 
691
}
 
692
 
 
693
/*----------------------------------------------------------------------*/
 
694
 
 
695
/*
 
696
 * This is a special version of recvariant_trie(), and it is only used by 
 
697
 * variant_answer_search().  The only difference between this and
 
698
 * recvariant_trie() is that this version will save the answer
 
699
 * substitution factor into the heap (see the following lines):
 
700
 *
 
701
 *      bld_free(hreg);
 
702
 *      bind_ref(xtemp1, hreg);
 
703
 *      xtemp1 = hreg++;
 
704
 */
 
705
 
 
706
#define recvariant_trie_ans_subsf(flag,TrieType) {                      \
 
707
  int  j;                                                               \
 
708
                                                                        \
 
709
  while (!pdlempty ) {                                                  \
 
710
    xtemp1 = (CPtr) pdlpop;                                             \
 
711
    XSB_CptrDeref(xtemp1);                                              \
 
712
    tag = cell_tag(xtemp1);                                             \
 
713
    switch (tag) {                                                      \
 
714
    case XSB_FREE:                                                      \
 
715
    case XSB_REF1:                                                      \
 
716
      if (! IsStandardizedVariable(xtemp1)){                            \
 
717
        bld_free(hreg);                                                 \
 
718
        bind_ref(xtemp1, hreg);                                         \
 
719
        xtemp1 = hreg++;                                                \
 
720
        StandardizeAndTrailVariable(xtemp1,ctr);                        \
 
721
        one_node_chk_ins(flag,EncodeNewTrieVar(ctr),TrieType);          \
 
722
        ctr++;                                                          \
 
723
      } else {                                                          \
 
724
        one_node_chk_ins(flag,                                          \
 
725
                         EncodeTrieVar(IndexOfStdVar(xtemp1)),          \
 
726
                         TrieType);                                     \
 
727
      }                                                                 \
 
728
      break;                                                            \
 
729
    case XSB_STRING:                                                    \
 
730
    case XSB_INT:                                                       \
 
731
    case XSB_FLOAT:                                                     \
 
732
      one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), TrieType);     \
 
733
      break;                                                            \
 
734
    case XSB_LIST:                                                      \
 
735
      one_node_chk_ins(flag, EncodeTrieList(xtemp1), TrieType);         \
 
736
      pdlpush(cell(clref_val(xtemp1)+1));                               \
 
737
      pdlpush(cell(clref_val(xtemp1)));                                 \
 
738
      break;                                                            \
 
739
    case XSB_STRUCT:                                                    \
 
740
      psc = (Psc) follow(cs_val(xtemp1));                               \
 
741
      item = makecs(psc);                                               \
 
742
      one_node_chk_ins(flag, item, TrieType);                           \
 
743
      for (j = get_arity(psc); j>=1 ; j--) {                            \
 
744
        pdlpush(cell(clref_val(xtemp1)+j));                             \
 
745
      }                                                                 \
 
746
      break;                                                            \
 
747
    case XSB_ATTV:                                                      \
 
748
      /* Now xtemp1 can only be the first occurrence of an attv */      \
 
749
      /* *(hreg++) = (Cell) xtemp1;     */                              \
 
750
      xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */        \
 
751
      StandardizeAndTrailVariable(xtemp1, ctr);                         \
 
752
      one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), TrieType);         \
 
753
      attv_ctr++; ctr++;                                                \
 
754
      pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */         \
 
755
      break;                                                            \
 
756
    default:                                                            \
 
757
      xsb_abort("Bad type tag in recvariant_trie_ans_subsf...\n");      \
 
758
    }                                                                   \
 
759
  }                                                                     \
 
760
  resetpdl;                                                             \
 
761
}
 
762
 
 
763
 
 
764
#include "term_psc_xsb_i.h"
 
765
#include "ptoc_tag_xsb_i.h"
 
766
 
 
767
 
 
768
/*
 
769
 * Called in SLG instruction `new_answer_dealloc', variant_answer_search()
 
770
 * checks if the answer has been returned before and, if not, inserts it
 
771
 * into the answer trie.  Here, `sf_size' is the number of variables in the
 
772
 * substitution factor of the called subgoal, `attv_num' is the number of
 
773
 * attributed variables in the call, `cptr' is the pointer to the
 
774
 * substitution factor, and `subgoal_ptr' is the subgoal frame of the
 
775
 * call.  At the end of this function, `flagptr' tells if the answer
 
776
 * has been returned before.
 
777
 *
 
778
 * The returned value of this function is the leaf of the answer trie.
 
779
 */
 
780
 
 
781
BTNptr variant_answer_search(CTXTdeclc int sf_size, int attv_num, CPtr cptr,
 
782
                             VariantSF subgoal_ptr, xsbBool *flagptr) {
 
783
 
 
784
  Psc   psc;
 
785
  CPtr  xtemp1;
 
786
  int   i, j, flag = 1;
 
787
  Cell  tag = XSB_FREE, item, tmp_var;
 
788
  ALNptr answer_node;
 
789
  int ctr, attv_ctr;
 
790
  BTNptr Paren, *GNodePtrPtr;
 
791
 
 
792
  ans_chk_ins++; /* Counter (answers checked & inserted) */
 
793
 
 
794
  VarEnumerator_trail_top = (CPtr *)(& VarEnumerator_trail[0]) - 1;
 
795
  AnsVarCtr = 0;
 
796
  ctr = 0;
 
797
  if ( IsNULL(subg_ans_root_ptr(subgoal_ptr)) ) {
 
798
    Cell retSymbol;
 
799
    if ( sf_size > 0 )
 
800
      retSymbol = EncodeTriePSC(get_ret_psc(sf_size));
 
801
    else
 
802
      retSymbol = EncodeTrieConstant(makestring(get_ret_string()));
 
803
    subg_ans_root_ptr(subgoal_ptr) =
 
804
      newBasicAnswerTrie(CTXTc retSymbol, (CPtr) subgoal_ptr, 
 
805
                         BASIC_ANSWER_TRIE_TT);
 
806
  }
 
807
  Paren = subg_ans_root_ptr(subgoal_ptr);
 
808
  GNodePtrPtr = &BTN_Child(Paren);
 
809
 
 
810
  /* Documentation rewritten by TLS: 
 
811
   * To properly generate instructions for attributed variables, you
 
812
   * need to know which attributed variables are identical to those in
 
813
   * the call, and which represent new bindings to attributed or vanilla
 
814
   * variables.  The marking below binds binds the VAR part of the
 
815
   * attvs to an element of VarEnumerator[].  When the for() loop
 
816
   * dereferences these variables they can be recognized as pointing
 
817
   * into VarEnumerator, and a trie_xxx_val instruction will be
 
818
   * generated for them.  Other attvs will dereference elsewhere and
 
819
   * will generate a trie_xxx_attv instruction.  Note that in doing
 
820
   * this, attributes in the call will not need to be re-entered in
 
821
   * the table.
 
822
   * 
 
823
   * According to Bao's algorithm, in order for trie instructions for
 
824
   * completed tables to work for attvs, attvs in the call must be
 
825
   * traversed before the main loop and bound to elements of
 
826
   * varEnumerator so that the trie_xxx_val instructions can recognize
 
827
   * them and avoid interrupts.  As a result, both here and in the tabletry
 
828
   * setup for completed tables, the substitution factor is traversed
 
829
   * and the attvs set to the lower portion of varEnumerator.  To save
 
830
   * time, this is only done when there is at least one attv in 
 
831
   * the call (attv_num > 0).  �
 
832
   */
 
833
  if (attv_num > 0) {
 
834
    for (i = 0; i < sf_size; i++) {
 
835
      tmp_var = cell(cptr - i);
 
836
      if (isattv(tmp_var)) {
 
837
        xtemp1 = clref_val(tmp_var); /* the VAR part */
 
838
        if (xtemp1 == (CPtr) cell(xtemp1)) { /* this attv is not changed */
 
839
          StandardizeAndTrailVariable(xtemp1, ctr);
 
840
        }
 
841
        ctr++;
 
842
      }
 
843
    }
 
844
    /* now ctr should be equal to attv_num */
 
845
  }
 
846
  attv_ctr = attv_num;
 
847
 
 
848
  for (i = 0; i < sf_size; i++) {
 
849
    xtemp1 = (CPtr) (cptr - i); /* One element of VarsInCall.  It might
 
850
                                 * have been bound in the answer for
 
851
                                 * the call.
 
852
                                 */
 
853
    XSB_CptrDeref(xtemp1);
 
854
    tag = cell_tag(xtemp1);
 
855
    switch (tag) {
 
856
    case XSB_FREE: 
 
857
    case XSB_REF1:
 
858
      if (! IsStandardizedVariable(xtemp1)) {
 
859
        /*
 
860
         * Note that unlike variant_call_search(), vas() trails
 
861
         * variables (by using VarEnumerator_trail_top, rather than
 
862
         * full SLG-WAM trailing.  Thus, if this is the first
 
863
         * occurrence of this variable, then: 
 
864
         *
 
865
         *      StandardizeAndTrailVariable(xtemp1, ctr)
 
866
         *                      ||
 
867
         *      bld_ref(xtemp1, VarEnumerator[ctr]);
 
868
         *      *(++VarEnumerator_trail_top) = xtemp1
 
869
         *
 
870
         * By doing this, all the variables appearing in the answer
 
871
         * are bound to elements in VarEnumerator[], and each element
 
872
         * in VarEnumerator[] is a free variable itself.  vcs() was
 
873
         * able to avoid the trail because all variables were placed
 
874
         * on the substitution factor; variables encountered in an
 
875
         * answer substitution can be anywhere on the heap.  Also
 
876
         * note that this function uses the pdl stack rather than
 
877
         * reg_array, as does vsc().
 
878
         * The variables will be used in 
 
879
         * delay_chk_insert() (in function do_delay_stuff()).
 
880
         */
 
881
 
 
882
#ifndef IGNORE_DELAYVAR
 
883
        bld_free(hreg); // make sure there is no pointer from heap to local stack.
 
884
        bind_ref(xtemp1, hreg);
 
885
        xtemp1 = hreg++;
 
886
#endif
 
887
        StandardizeAndTrailVariable(xtemp1,ctr);
 
888
        item = EncodeNewTrieVar(ctr);
 
889
        one_node_chk_ins(flag, item, BASIC_ANSWER_TRIE_TT);
 
890
        ctr++;
 
891
      } else {
 
892
        item = IndexOfStdVar(xtemp1);
 
893
        item = EncodeTrieVar(item);
 
894
        one_node_chk_ins(flag, item, BASIC_ANSWER_TRIE_TT);
 
895
      }
 
896
      break;
 
897
    case XSB_STRING: 
 
898
    case XSB_INT:
 
899
    case XSB_FLOAT:
 
900
      one_node_chk_ins(flag, EncodeTrieConstant(xtemp1),
 
901
                       BASIC_ANSWER_TRIE_TT);
 
902
      break;
 
903
    case XSB_LIST:
 
904
      one_node_chk_ins(flag, EncodeTrieList(xtemp1), BASIC_ANSWER_TRIE_TT);
 
905
      pdlpush(cell(clref_val(xtemp1)+1));
 
906
      pdlpush(cell(clref_val(xtemp1)));
 
907
#ifndef IGNORE_DELAYVAR
 
908
      recvariant_trie_ans_subsf(flag, BASIC_ANSWER_TRIE_TT);
 
909
#else
 
910
      recvariant_trie(flag, BASIC_ANSWER_TRIE_TT);
 
911
#endif 
 
912
      break;
 
913
    case XSB_STRUCT:
 
914
      psc = (Psc)follow(cs_val(xtemp1));
 
915
      item = makecs(psc);
 
916
      one_node_chk_ins(flag, item, BASIC_ANSWER_TRIE_TT);
 
917
      for (j = get_arity(psc); j >= 1 ; j--) {
 
918
        pdlpush(cell(clref_val(xtemp1)+j));
 
919
      }
 
920
#ifndef IGNORE_DELAYVAR
 
921
      recvariant_trie_ans_subsf(flag, BASIC_ANSWER_TRIE_TT);
 
922
#else
 
923
      recvariant_trie(flag, BASIC_ANSWER_TRIE_TT);
 
924
#endif
 
925
      break;
 
926
    case XSB_ATTV:
 
927
      /* Now xtemp1 can only be the first occurrence of an attv */
 
928
      //      *(hreg++) = (Cell) xtemp1;
 
929
      xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
 
930
      /*
 
931
       * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
 
932
       * later occurrences of this attv will look like a regular variable
 
933
       * (after dereferencing).
 
934
       */
 
935
      StandardizeAndTrailVariable(xtemp1, ctr); 
 
936
      one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), BASIC_ANSWER_TRIE_TT);
 
937
      attv_ctr++; ctr++;
 
938
      pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */
 
939
#ifndef IGNORE_DELAYVAR
 
940
      recvariant_trie_ans_subsf(flag, BASIC_ANSWER_TRIE_TT);
 
941
#else
 
942
      recvariant_trie(flag, BASIC_ANSWER_TRIE_TT);
 
943
#endif
 
944
      break;
 
945
    default:
 
946
      xsb_abort("Bad type tag in variant_answer_search()");
 
947
    }                                                       
 
948
  }
 
949
  resetpdl;                                                   
 
950
 
 
951
#ifndef IGNORE_DELAYVAR
 
952
  /*
 
953
   * Put the substitution factor of the answer into a term ret/n (if 
 
954
   * the sf_size of the substitution factor is 0, then put integer 0
 
955
   * into cell ans_var_pos_reg).
 
956
   *
 
957
   * Notice that simple_table_undo_bindings in pre-1.9 version of XSB
 
958
   * has been removed here, because all the variable bindings of this
 
959
   * answer will be used in do_delay_stuff() immediatly after the
 
960
   * return of vas() when we build the delay list for this answer.
 
961
   */
 
962
  if (ctr == 0)
 
963
    bld_int(ans_var_pos_reg, 0);
 
964
  else  
 
965
    bld_functor(ans_var_pos_reg, get_ret_psc(ctr));
 
966
#else /* IGNORE_DELAYVAR */
 
967
  undo_answer_bindings(CTXT);
 
968
#endif
 
969
 
 
970
  /*
 
971
     * Save the number of variables in the answer, i.e. the sf_size of
 
972
     * the substitution factor of the answer, into `AnsVarCtr'.
 
973
     */
 
974
  AnsVarCtr = ctr;              
 
975
 
 
976
#ifdef DEBUG_DELAYVAR
 
977
  xsb_dbgmsg((LOG_DEBUG,">>>> [V] AnsVarCtr = %d", AnsVarCtr));
 
978
#endif
 
979
 
 
980
  /* if there is no term to insert, an ESCAPE node has to be created/found */
 
981
 
 
982
  if (sf_size == 0) {
 
983
    one_node_chk_ins(flag, ESCAPE_NODE_SYMBOL, BASIC_ANSWER_TRIE_TT);
 
984
    Instr(Paren) = trie_proceed;
 
985
  }
 
986
 
 
987
  /*
 
988
   *  If an insertion was performed, do some maintenance on the new leaf,
 
989
   *  and place the answer handle onto the answer list.
 
990
   */
 
991
  if ( flag == 0 ) {
 
992
    MakeLeafNode(Paren);
 
993
    TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
 
994
    ans_inserts++;
 
995
 
 
996
    New_ALN(subgoal_ptr,answer_node,Paren,NULL);
 
997
    SF_AppendNewAnswer(subgoal_ptr,answer_node);
 
998
  }
 
999
 
 
1000
  *flagptr = flag;      
 
1001
  return Paren;
 
1002
}
 
1003
 
 
1004
/*
 
1005
 * undo_answer_bindings() has the same functionality of
 
1006
 * simple_table_undo_bindings.  It is called just after do_delay_stuff(),
 
1007
 * and do_delay_stuff() is called after variant_answer_search (in
 
1008
 * new_answer_dealloc)
 
1009
 *
 
1010
 * In XSB 1.8.1, simple_table_undo_bindings is called in
 
1011
 * variant_answer_search().  But to handle variables in delay list in
 
1012
 * do_delay_stuff() , we need the variable binding information got from
 
1013
 * variant_answer_search().  So we have to take simple_table_undo_bindings
 
1014
 * out of variant_answer_search() and call it after do_delay_stuff() is
 
1015
 * done.
 
1016
 */
 
1017
 
 
1018
void undo_answer_bindings(CTXTdecl) {
 
1019
  simple_table_undo_bindings;
 
1020
}
 
1021
 
 
1022
/*
 
1023
 * Function delay_chk_insert() is called only from intern_delay_element()
 
1024
 * to create the delay trie for the corresponding delay element.  This
 
1025
 * delay trie contains the substitution factor of the answer to the subgoal
 
1026
 * call of this delay element.  Its leaf node will be saved as a field,
 
1027
 * de_subs_fact_leaf, in the delay element.
 
1028
 *
 
1029
 * This function is closely related to variant_answer_search(), because it
 
1030
 * uses the value of AnsVarCtr that is set in variant_answer_search().  The
 
1031
 * body of this function is almost the same as the core part of
 
1032
 * variant_answer_search(), except that `ctr', the counter of the variables
 
1033
 * in the answer, starts from AnsVarCtr.  Initially, before the first delay
 
1034
 * element in the delay list of a subgoal (say p/2), is interned, AnsVarCtr
 
1035
 * is the number of variables in the answer for p/2 and it was set in
 
1036
 * variant_answer_search() when this answer was returned.  Then, AnsVarCtr
 
1037
 * will be dynamically increased as more and more delay elements for p/2
 
1038
 * are interned.
 
1039
 *
 
1040
 * After variant_answer_search() is finished, VarEnumerator[] contains the
 
1041
 * variables in the head of the corresponding clause for p/2.  When we call
 
1042
 * delay_chk_insert() to intern the delay list for p/2, VarEnumerator[]
 
1043
 * will be used again to bind the variables that appear in the body.
 
1044
 * Because we have to check if a variable in a delay element of p/2 is
 
1045
 * already in the head, the old bindings of variables to VarEnumerator[]
 
1046
 * are still needed.  So undo_answer_bindings has to be delayed.
 
1047
 *
 
1048
 * In the arguments, `arity' is the arity of the the answer substitution
 
1049
 * factor, `cptr' points to the first field of term ret/n (the answer
 
1050
 * substitution factor), `hook' is a pointer to a location where the top of
 
1051
 * this delay trie will become anchored.  Since these delay "tries" only
 
1052
 * occur as single paths, there is currently no need for a root node.
 
1053
 */
 
1054
 
 
1055
BTNptr delay_chk_insert(CTXTdeclc int arity, CPtr cptr, CPtr *hook)
 
1056
{
 
1057
    Psc  psc;
 
1058
    Cell item;
 
1059
    CPtr xtemp1;
 
1060
    int  i, j, tag = XSB_FREE, flag = 1;
 
1061
    int ctr, attv_ctr;
 
1062
    BTNptr Paren, *GNodePtrPtr;
 
1063
 
 
1064
#ifdef DEBUG_DELAYVAR
 
1065
    xsb_dbgmsg((LOG_DEBUG,">>>> start delay_chk_insert()"));
 
1066
#endif
 
1067
 
 
1068
    Paren = NULL;
 
1069
    GNodePtrPtr = (BTNptr *) hook;
 
1070
 
 
1071
    ctr = AnsVarCtr;
 
1072
 
 
1073
#ifdef DEBUG_DELAYVAR
 
1074
    xsb_dbgmsg((LOG_DEBUG,">>>> [D1] AnsVarCtr = %d", AnsVarCtr));
 
1075
#endif
 
1076
 
 
1077
    for (i = 0; i<arity; i++) {
 
1078
      /*
 
1079
       * Notice: the direction of saving the variables in substitution
 
1080
       * factors has been changed.  Because Prasad saves the substitution
 
1081
       * factors in CP stack (--VarPosReg), but I save them in heap
 
1082
       * (hreg++).  So (cptr - i) is changed to (cptr + i) in the
 
1083
       * following line.
 
1084
       */
 
1085
      xtemp1 = (CPtr) (cptr + i);
 
1086
      xsb_dbgmsg((LOG_BD, "arg[%d] =  %x ",i, xtemp1));
 
1087
      XSB_CptrDeref(xtemp1);
 
1088
      dbg_printterm(LOG_BD,stddbg,(unsigned int)xtemp1,25);
 
1089
      xsb_dbgmsg((LOG_BD, "\n"));
 
1090
      tag = cell_tag(xtemp1);
 
1091
      switch (tag) {
 
1092
      case XSB_FREE:
 
1093
      case XSB_REF1:
 
1094
        if (! IsStandardizedVariable(xtemp1)) {
 
1095
          StandardizeAndTrailVariable(xtemp1,ctr);
 
1096
          one_node_chk_ins(flag,EncodeNewTrieVar(ctr),
 
1097
                           DELAY_TRIE_TT);
 
1098
          ctr++;
 
1099
        }
 
1100
        else {
 
1101
          one_node_chk_ins(flag,
 
1102
                           EncodeTrieVar(IndexOfStdVar(xtemp1)),
 
1103
                           DELAY_TRIE_TT);
 
1104
        }
 
1105
        break;
 
1106
      case XSB_STRING: 
 
1107
      case XSB_INT:
 
1108
      case XSB_FLOAT:
 
1109
        one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), DELAY_TRIE_TT);
 
1110
        break;
 
1111
      case XSB_LIST:
 
1112
        one_node_chk_ins(flag, EncodeTrieList(xtemp1), DELAY_TRIE_TT);
 
1113
        pdlpush(cell(clref_val(xtemp1)+1));
 
1114
        pdlpush(cell(clref_val(xtemp1)));
 
1115
        recvariant_trie(flag,DELAY_TRIE_TT);
 
1116
        break;
 
1117
      case XSB_STRUCT:
 
1118
        one_node_chk_ins(flag, makecs(follow(cs_val(xtemp1))),DELAY_TRIE_TT);
 
1119
        for (j = get_arity((Psc)follow(cs_val(xtemp1))); j >= 1 ; j--) {
 
1120
          pdlpush(cell(clref_val(xtemp1)+j));
 
1121
        }
 
1122
        recvariant_trie(flag,DELAY_TRIE_TT);
 
1123
        break;
 
1124
      case XSB_ATTV:
 
1125
        //      /* Now xtemp1 can only be the first occurrence of an attv */
 
1126
        //      *(hreg++) = (Cell) xtemp1;
 
1127
        xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
 
1128
        /*
 
1129
         * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
 
1130
         * later occurrences of this attv will look like a regular variable
 
1131
         * (after dereferencing).
 
1132
         */
 
1133
        if (! IsStandardizedVariable(xtemp1)) {
 
1134
          StandardizeAndTrailVariable(xtemp1, ctr);     
 
1135
          one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), DELAY_TRIE_TT);
 
1136
          ctr++; attv_ctr++;
 
1137
        }
 
1138
        else {
 
1139
          one_node_chk_ins(flag,
 
1140
                           EncodeTrieVar(IndexOfStdVar(xtemp1)),
 
1141
                           DELAY_TRIE_TT);
 
1142
        }
 
1143
        pdlpush(cell(xtemp1+1));        /* the ATTR part of the attv */
 
1144
        recvariant_trie(flag, DELAY_TRIE_TT);
 
1145
        break;
 
1146
      default:
 
1147
          xsb_abort("Bad type tag in delay_chk_insert()\n");
 
1148
        }
 
1149
    }
 
1150
    resetpdl;  
 
1151
    AnsVarCtr = ctr;
 
1152
 
 
1153
#ifdef DEBUG_DELAYVAR
 
1154
    xsb_dbgmsg((LOG_DEBUG,">>>> [D2] AnsVarCtr = %d", AnsVarCtr));
 
1155
#endif
 
1156
 
 
1157
    /*
 
1158
     *  If an insertion was performed, do some maintenance on the new leaf.
 
1159
     */
 
1160
    if ( flag == 0 ) {
 
1161
      MakeLeafNode(Paren);
 
1162
      TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
 
1163
    }
 
1164
 
 
1165
    xsb_dbgmsg((LOG_BD, "----------------------------- Exit\n"));
 
1166
    return Paren;
 
1167
}
 
1168
 
 
1169
/*----------------------------------------------------------------------*/
 
1170
/* for each variable in call, builds its binding on the heap.           */
 
1171
/*----------------------------------------------------------------------*/
 
1172
 
 
1173
/*
 
1174
 * Expects that the path in the trie -- to which the variables (stored in
 
1175
 * the vector `cptr') are to be unified -- has been pushed onto the
 
1176
 * termstack.
 
1177
 */
 
1178
static void load_solution_from_trie(CTXTdeclc int arity, CPtr cptr)
 
1179
{
 
1180
   int i;
 
1181
   CPtr xtemp1, Dummy_Addr;
 
1182
   Cell returned_val, xtemp2;
 
1183
 
 
1184
   for (i=0; i<arity; i++) {
 
1185
     xtemp1 = (CPtr) (cptr-i);
 
1186
     XSB_CptrDeref(xtemp1);
 
1187
     macro_make_heap_term(xtemp1,returned_val,Dummy_Addr);
 
1188
     if (xtemp1 != (CPtr)returned_val) {
 
1189
       if (isref(xtemp1)) {     /* a regular variable */
 
1190
         dbind_ref(xtemp1,returned_val);
 
1191
       }
 
1192
       else {                   /* an XSB_ATTV */
 
1193
         /* Bind the variable part of xtemp1 to returned_val */
 
1194
         add_interrupt(CTXTc cell(((CPtr)dec_addr(xtemp1) + 1)), returned_val); 
 
1195
         dbind_ref((CPtr) dec_addr(xtemp1), returned_val);
 
1196
       }
 
1197
     }
 
1198
   }
 
1199
   resetpdl;
 
1200
}
 
1201
 
 
1202
/*----------------------------------------------------------------------*/
 
1203
 
 
1204
/*
 
1205
 * Unifies the path in the interned trie identified by `Leaf' with the term
 
1206
 * `term'.  It appears that `term' is expected to be an unbound variable.
 
1207
 * Also, `Root' does not appear to be used.
 
1208
 */
 
1209
static void bottomupunify(CTXTdeclc Cell term, BTNptr Root, BTNptr Leaf)
 
1210
{
 
1211
  CPtr Dummy_Addr;
 
1212
  Cell returned_val, xtemp2;
 
1213
  CPtr gen;
 
1214
  int  i;
 
1215
 
 
1216
  num_heap_term_vars = 0;     
 
1217
  follow_par_chain(CTXTc Leaf);
 
1218
  XSB_Deref(term);
 
1219
  gen = (CPtr) term;
 
1220
  macro_make_heap_term(gen,returned_val,Dummy_Addr);
 
1221
  bld_ref(gen,returned_val);
 
1222
 
 
1223
  for(i = 0; i < num_heap_term_vars; i++){
 
1224
    var_regs[i] = var_addr[i];
 
1225
  }
 
1226
  /*
 
1227
   * global_num_vars is needed by get_lastnode_cs_retskel() (see
 
1228
   * trie_interned/4 in intern.P).
 
1229
   *
 
1230
   * Last_Nod_Sav is also needed by get_lastnode_cs_retskel().  We can
 
1231
   * set it to Leaf.
 
1232
   */
 
1233
  global_num_vars = num_vars_in_var_regs = num_heap_term_vars - 1;
 
1234
  Last_Nod_Sav = Leaf;
 
1235
}
 
1236
 
 
1237
/*----------------------------------------------------------------------*/
 
1238
 
 
1239
/*
 
1240
 *  Used with tries created via the builtin trie_intern.
 
1241
 */
 
1242
 
 
1243
#ifndef MULTI_THREAD
 
1244
  extern  BTNptr *Set_ArrayPtr;
 
1245
#endif
 
1246
 
 
1247
xsbBool bottom_up_unify(CTXTdecl)
 
1248
{
 
1249
  Cell    term;
 
1250
  BTNptr root;
 
1251
  BTNptr leaf;
 
1252
  int     rootidx;
 
1253
 
 
1254
  leaf = (BTNptr) ptoc_int(CTXTc 3);   
 
1255
  if( IsDeletedNode(leaf) )
 
1256
    return FALSE;
 
1257
 
 
1258
  term    = ptoc_tag(CTXTc 1);
 
1259
  rootidx = ptoc_int(CTXTc 2);
 
1260
  root    = Set_ArrayPtr[rootidx];  
 
1261
  bottomupunify(CTXTc term, root, leaf);
 
1262
  return TRUE;
 
1263
}
 
1264
 
 
1265
/*----------------------------------------------------------------------*/
 
1266
 
 
1267
/*
 
1268
 * `TriePtr' is a leaf in the answer trie, and `cptr' is a vector of
 
1269
 * variables for receiving the substitution.
 
1270
 */
 
1271
void load_solution_trie(CTXTdeclc int arity, int attv_num, CPtr cptr, BTNptr TriePtr)
 
1272
{
 
1273
  CPtr xtemp;
 
1274
  
 
1275
  num_heap_term_vars = 0;
 
1276
  if (arity > 0) {
 
1277
    /* Initialize var_addr[] as the attvs in the call. */
 
1278
    if (attv_num > 0) {
 
1279
      for (xtemp = cptr; xtemp > cptr - arity; xtemp--) {
 
1280
        if (isattv(cell(xtemp))) {
 
1281
          //      var_addr[num_heap_term_vars] = (CPtr) cell(xtemp);
 
1282
          safe_assign(var_addr,num_heap_term_vars,(CPtr) cell(xtemp),var_addr_arraysz);
 
1283
          num_heap_term_vars++;
 
1284
        }
 
1285
      }
 
1286
    }
 
1287
    follow_par_chain(CTXTc TriePtr);
 
1288
    load_solution_from_trie(CTXTc arity,cptr);
 
1289
  }
 
1290
}
 
1291
 
 
1292
/*----------------------------------------------------------------------*/
 
1293
 
 
1294
void load_delay_trie(CTXTdeclc int arity, CPtr cptr, BTNptr TriePtr)
 
1295
{
 
1296
   if (arity) {
 
1297
     follow_par_chain(CTXTc TriePtr);
 
1298
     load_solution_from_trie(CTXTc arity,cptr);
 
1299
   }
 
1300
}
 
1301
 
 
1302
/*----------------------------------------------------------------------*/
 
1303
 
 
1304
#define recvariant_call(flag,TrieType,xtemp1) {                         \
 
1305
  int  j;                                                               \
 
1306
                                                                        \
 
1307
  while (!pdlempty) {                                                   \
 
1308
    xtemp1 = (CPtr) pdlpop;                                             \
 
1309
    XSB_CptrDeref(xtemp1);                                              \
 
1310
    switch(tag = cell_tag(xtemp1)) {                                    \
 
1311
    case XSB_FREE:                                                      \
 
1312
    case XSB_REF1:                                                      \
 
1313
      if (! IsStandardizedVariable(xtemp1)) {                           \
 
1314
        *(--VarPosReg) = (Cell) xtemp1;                                 \
 
1315
        StandardizeVariable(xtemp1,ctr);                                \
 
1316
        one_node_chk_ins(flag,EncodeNewTrieVar(ctr),TrieType);          \
 
1317
        ctr++;                                                          \
 
1318
      } else{                                                           \
 
1319
        one_node_chk_ins(flag, EncodeTrieVar(IndexOfStdVar(xtemp1)),    \
 
1320
                         TrieType);                                     \
 
1321
      }                                                                 \
 
1322
      break;                                                            \
 
1323
    case XSB_STRING:                                                    \
 
1324
    case XSB_INT:                                                       \
 
1325
    case XSB_FLOAT:                                                     \
 
1326
      one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), TrieType);     \
 
1327
      break;                                                            \
 
1328
    case XSB_LIST:                                                      \
 
1329
      one_node_chk_ins(flag, EncodeTrieList(xtemp1), TrieType);         \
 
1330
      pdlpush( cell(clref_val(xtemp1)+1) );                             \
 
1331
      pdlpush( cell(clref_val(xtemp1)) );                               \
 
1332
      break;                                                            \
 
1333
    case XSB_STRUCT:                                                    \
 
1334
      psc = (Psc) follow(cs_val(xtemp1));                               \
 
1335
      item = makecs(psc);                                               \
 
1336
      one_node_chk_ins(flag, item, TrieType);                           \
 
1337
      for (j=get_arity(psc); j>=1; j--) {                               \
 
1338
        pdlpush(cell(clref_val(xtemp1)+j));                             \
 
1339
      }                                                                 \
 
1340
      break;                                                            \
 
1341
    case XSB_ATTV:                                                      \
 
1342
      /* Now xtemp1 can only be the first occurrence of an attv */      \
 
1343
      *(--VarPosReg) = (Cell) xtemp1;                                   \
 
1344
      xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */        \
 
1345
      StandardizeVariable(xtemp1, ctr);                                 \
 
1346
      one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), TrieType);         \
 
1347
      attv_ctr++; ctr++;                                                \
 
1348
      pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */         \
 
1349
      break;                                                            \
 
1350
    default:                                                            \
 
1351
      xsb_abort("Bad type tag in recvariant_call...\n");                \
 
1352
    }                                                                   \
 
1353
  }                                                                     \
 
1354
  resetpdl;                                                             \
 
1355
}
 
1356
 
 
1357
/*----------------------------------------------------------------------*/
 
1358
 
 
1359
/* TLS gloss: 
 
1360
 * 
 
1361
 * To me it seems this function is written in an overly general way.
 
1362
 * I dont see a real need to encapsulate all of its input and output
 
1363
 * as it is only called once, in tabletry.  What's lost is: 
 
1364
 * cptr is simply a pointer to the reg_array, cptr = reg+1 
 
1365
 * VarPosReg is top_of_cpstack.  This can cause confusion since later in
 
1366
 * table_call_search (which calls this function) the substitution
 
1367
 * factor is copied to the heap.
 
1368
 * 
 
1369
 * In addition, the manner in which attributed variables are handled
 
1370
 * gives rise to some special features in the code.  When adding an
 
1371
 * answer, it is not straightforward to determine whether a binding
 
1372
 * to a substitution factor was made in the original call or as part
 
1373
 * of program clause resolution.  variant_call_search() creates a
 
1374
 * substitution factor on the choice point stack.  Immediately after
 
1375
 * variant_call_search() returns, table_call_search() will copy the
 
1376
 * substitution factor from the choice point stack to the heap.  It
 
1377
 * can then be determined whether attributed variables are old or new
 
1378
 * by comparing the value of a cell in the choice point stack to the
 
1379
 * corresponding value in the heap.  If they are the same, the
 
1380
 * attributed variable was in the call, and a trie_xxx_val
 
1381
 * instruction can be used.  If not, other actions must be taken --
 
1382
 * generating either a trie_xxx_val or trie_xxx_attv.
 
1383
 * 
 
1384
 * While most of this happens in later functions, certain
 
1385
 * features of vcs() can be accounted for by these later actions.
 
1386
 * For instance, each local variable is copied to the heap in vcs().
 
1387
 * This is to avoid pointers from the heap substitution factor (once
 
1388
 * it is created) into the local stack.
 
1389
 *
 
1390
 */
 
1391
 
 
1392
/*
 
1393
 * Searches/inserts a subgoal call structure into a subgoal call trie.
 
1394
 * During search/insertion, the variables of the subgoal call are
 
1395
 * pushed on top of the CP stack (through VarPosReg), along with the #
 
1396
 * of variables that were pushed.  This forms the substitution factor.
 
1397
 * Prolog variables are standardized during this process to recognize
 
1398
 * multiple (nonlinear) occurences.  They must be reset to an unbound
 
1399
 * state before termination.
 
1400
 * 
 
1401
 * Important variables: 
 
1402
 * Paren - to be set to point to inserted term's leaf
 
1403
 * VarPosReg - pointer to top of CPS; place to put the substitution factor
 
1404
 *    in high-to-low memory format.
 
1405
 * GNodePtrPtr - Points to the parent-internal-structure's
 
1406
 *    "child" or "NODE_link" field.  It's a place to anchor any newly
 
1407
 *    created NODEs.
 
1408
 * ctr - contains the number of distinct variables found
 
1409
 *    in the call.
 
1410
 * Pay careful attention to the expected argument vector accepted by this
 
1411
 * function.  It actually points one Cell *before* the term vector!  Notice
 
1412
 * the treatment of "cptr" as these terms are inspected.
 
1413
 */
 
1414
 
 
1415
void variant_call_search(CTXTdeclc TabledCallInfo *call_info,
 
1416
                         CallLookupResults *results)
 
1417
{
 
1418
  Psc  psc;
 
1419
  CPtr call_arg;
 
1420
  int  arity, i, j, flag = 1;
 
1421
  Cell tag = XSB_FREE, item;
 
1422
  CPtr cptr, VarPosReg, tVarPosReg;
 
1423
  int ctr, attv_ctr;
 
1424
  BTNptr Paren, *GNodePtrPtr;
 
1425
 
 
1426
  subg_chk_ins++;
 
1427
  Paren = TIF_CallTrie(CallInfo_TableInfo(*call_info));
 
1428
  GNodePtrPtr = &BTN_Child(Paren);
 
1429
  arity = CallInfo_CallArity(*call_info);
 
1430
  /* cptr is set to point to the reg_array */
 
1431
  cptr = CallInfo_Arguments(*call_info);
 
1432
  tVarPosReg = VarPosReg = CallInfo_VarVectorLoc(*call_info);
 
1433
  ctr = attv_ctr = 0;
 
1434
 
 
1435
  for (i = 0; i < arity; i++) {
 
1436
    xsb_dbgmsg((LOG_DEBUG,">>>> (argument %d)",i+1));
 
1437
    call_arg = (CPtr) (cptr + i);            /* Note! */
 
1438
    XSB_CptrDeref(call_arg);
 
1439
    tag = cell_tag(call_arg);
 
1440
    switch (tag) {
 
1441
    case XSB_FREE:
 
1442
    case XSB_REF1:
 
1443
      if (! IsStandardizedVariable(call_arg)) {
 
1444
 
 
1445
        /* Call_arg is now a dereferenced register value.  If it
 
1446
         * points to a local variable, make both the local variable
 
1447
         * and call_arg point to a new free variable in the heap.
 
1448
         * As noted in the documentation at the start of this function,
 
1449
         * this is to support attributed variables in tabling.   
 
1450
         */
 
1451
 
 
1452
        xsb_dbgmsg((LOG_DEBUG,"   new variable ctr = %d)",ctr));
 
1453
 
 
1454
        if (top_of_localstk <= call_arg &&
 
1455
            call_arg <= (CPtr) glstack.high - 1) {
 
1456
          bld_free(hreg);
 
1457
          bind_ref(call_arg, hreg);
 
1458
          call_arg = hreg++;
 
1459
        }
 
1460
        /*
 
1461
         * Make VarPosReg, which points to the top of the choice point
 
1462
         * stack, point to call_arg, which now points a free variable in the
 
1463
         * heap.  Make that heap free variable point to the
 
1464
         * VarEnumerator array, via StandardizeVariable.   The
 
1465
         * VarEnumerator array contains variables that point to
 
1466
         * themselves (init'd in init_trie_aux_areas()).  vcs() does
 
1467
         * not change bindings in the VarEnumerator array -- it just
 
1468
         * changes bindings of heap variables that point into it.
 
1469
         */
 
1470
        *(--VarPosReg) = (Cell) call_arg;       
 
1471
        StandardizeVariable(call_arg,ctr);
 
1472
        one_node_chk_ins(flag,EncodeNewTrieVar(ctr),
 
1473
                         CALL_TRIE_TT);
 
1474
        ctr++;
 
1475
      } else {
 
1476
        one_node_chk_ins(flag,EncodeTrieVar(IndexOfStdVar(call_arg)),CALL_TRIE_TT);
 
1477
      }
 
1478
      break;
 
1479
    case XSB_STRING:
 
1480
    case XSB_INT:
 
1481
    case XSB_FLOAT:
 
1482
      one_node_chk_ins(flag, EncodeTrieConstant(call_arg), CALL_TRIE_TT);
 
1483
      break;
 
1484
    case XSB_LIST:
 
1485
      one_node_chk_ins(flag, EncodeTrieList(call_arg), CALL_TRIE_TT);
 
1486
      pdlpush(cell(clref_val(call_arg)+1));
 
1487
      pdlpush(cell(clref_val(call_arg)));
 
1488
      recvariant_call(flag,CALL_TRIE_TT,call_arg);
 
1489
      break;
 
1490
    case XSB_STRUCT:
 
1491
      psc = (Psc)follow(cs_val(call_arg));
 
1492
      item = makecs(psc);
 
1493
      one_node_chk_ins(flag, item, CALL_TRIE_TT);
 
1494
      for (j=get_arity(psc); j>=1 ; j--) {
 
1495
        pdlpush(cell(clref_val(call_arg)+j));
 
1496
      }
 
1497
      recvariant_call(flag,CALL_TRIE_TT,call_arg);
 
1498
      break;
 
1499
    case XSB_ATTV:
 
1500
      /* call_arg is derefed register value pointing to heap.  Make
 
1501
         the subst factor CP-stack pointer, VarPosReg, point to it. */
 
1502
      *(--VarPosReg) = (Cell) call_arg;
 
1503
      xsb_dbgmsg((LOG_TRIE,"In VSC: attv deref'd reg %x; val: %x into AT: %x",
 
1504
                 call_arg,clref_val(call_arg),VarPosReg));
 
1505
      call_arg = clref_val(call_arg); /* the VAR part of the attv */
 
1506
      /*
 
1507
       * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
 
1508
       * later occurrences of this attv will look like a regular variable
 
1509
       * (after dereferencing).
 
1510
       */
 
1511
      StandardizeVariable(call_arg, ctr);       
 
1512
      one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), CALL_TRIE_TT);
 
1513
      attv_ctr++; ctr++;
 
1514
      pdlpush(cell(call_arg+1));        /* the ATTR part of the attv */
 
1515
      recvariant_call(flag, CALL_TRIE_TT, call_arg);
 
1516
      break;
 
1517
    default:
 
1518
      xsb_abort("Bad type tag in variant_call_search...\n");
 
1519
    }
 
1520
  }
 
1521
  resetpdl;
 
1522
    
 
1523
  if (arity == 0) {
 
1524
    one_node_chk_ins(flag, ESCAPE_NODE_SYMBOL, CALL_TRIE_TT);
 
1525
    Instr(Paren) = trie_proceed;
 
1526
  }
 
1527
 
 
1528
  /*
 
1529
   *  If an insertion was performed, do some maintenance on the new leaf.
 
1530
   */
 
1531
  if ( flag == 0 ) {
 
1532
    subg_inserts++;
 
1533
    MakeLeafNode(Paren);
 
1534
    TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
 
1535
  }
 
1536
 
 
1537
  cell(--VarPosReg) = makeint(attv_ctr << 16 | ctr);
 
1538
  /* 
 
1539
   * "Untrail" any variable that used to point to VarEnumerator.  For
 
1540
   * variables, note that *VarPosReg is the address of a cell in the
 
1541
   * heap.  To reset that variable, we make that address free.
 
1542
   * Similarly, *VarPosReg may contain the (encoded) address of an
 
1543
   * attv on the heap.  In this case, we make the VAR part of that
 
1544
   * attv point to itself.  The actual value in VarPosReg (i.e. the
 
1545
   * of a substitution factor) doesn't change in either case.
 
1546
   */     
 
1547
  while (--tVarPosReg > VarPosReg) {
 
1548
    if (isref(*tVarPosReg))     /* a regular variable */
 
1549
      ResetStandardizedVariable(*tVarPosReg);
 
1550
    else                        /* an XSB_ATTV */
 
1551
      ResetStandardizedVariable(clref_val(*tVarPosReg));
 
1552
  }
 
1553
 
 
1554
  CallLUR_Leaf(*results) = Paren;
 
1555
  CallLUR_Subsumer(*results) = CallTrieLeaf_GetSF(Paren);
 
1556
  CallLUR_VariantFound(*results) = flag;
 
1557
  CallLUR_VarVector(*results) = VarPosReg;
 
1558
  return;
 
1559
}
 
1560
 
 
1561
/*----------------------------------------------------------------------*/
 
1562
 
 
1563
static void remove_calls_and_returns(CTXTdeclc VariantSF CallStrPtr)
 
1564
{
 
1565
  ALNptr pALN;
 
1566
 
 
1567
  /* Delete the call entry
 
1568
     --------------------- */
 
1569
  SET_TRIE_ALLOCATION_TYPE_SF(CallStrPtr);
 
1570
  delete_branch(CTXTc subg_leaf_ptr(CallStrPtr),
 
1571
                &TIF_CallTrie(subg_tif_ptr(CallStrPtr)));
 
1572
 
 
1573
  /* Delete its answers
 
1574
     ------------------ */
 
1575
  for ( pALN = subg_answers(CallStrPtr);  IsNonNULL(pALN);
 
1576
        pALN = ALN_Next(pALN) )
 
1577
    delete_branch(CTXTc ALN_Answer(pALN), &subg_ans_root_ptr(CallStrPtr));
 
1578
 
 
1579
  /* Delete the table entry
 
1580
     ---------------------- */
 
1581
  free_answer_list(CallStrPtr);
 
1582
  FreeProducerSF(CallStrPtr);
 
1583
}
 
1584
 
 
1585
void remove_incomplete_tries(CTXTdeclc CPtr bottom_parameter)
 
1586
{
 
1587
  xsbBool warned = FALSE;
 
1588
  VariantSF CallStrPtr;
 
1589
 
 
1590
  while (openreg < bottom_parameter) {
 
1591
    CallStrPtr = (VariantSF)compl_subgoal_ptr(openreg);
 
1592
    if (!is_completed(CallStrPtr)) {
 
1593
      if (warned == FALSE) {
 
1594
        xsb_mesg("Removing incomplete tables...");
 
1595
        //      check_table_cut = FALSE;  /* permit cuts over tables */
 
1596
        warned = TRUE;
 
1597
      }
 
1598
      remove_calls_and_returns(CTXTc CallStrPtr);
 
1599
    }
 
1600
    openreg += COMPLFRAMESIZE;
 
1601
  }
 
1602
}
 
1603
 
 
1604
/*----------------------------------------------------------------------*/
 
1605
 
 
1606
/*
 
1607
 * For creating interned tries via buitin "trie_intern".
 
1608
 */
 
1609
 
 
1610
BTNptr whole_term_chk_ins(CTXTdeclc Cell term, BTNptr *hook, int *flagptr)
 
1611
{
 
1612
    Psc  psc;
 
1613
    CPtr xtemp1;
 
1614
    int  j, flag = 1;
 
1615
    Cell tag = XSB_FREE, item;
 
1616
    int ctr, attv_ctr;
 
1617
    BTNptr Paren, *GNodePtrPtr;
 
1618
 
 
1619
 
 
1620
    if ( IsNULL(*hook) )
 
1621
      *hook = newBasicTrie(CTXTc EncodeTriePSC(get_intern_psc()),INTERN_TRIE_TT);
 
1622
    Paren = *hook;
 
1623
    GNodePtrPtr = &BTN_Child(Paren);
 
1624
 
 
1625
    xtemp1 = (CPtr) term;
 
1626
    XSB_CptrDeref(xtemp1);
 
1627
    tag = cell_tag(xtemp1);
 
1628
 
 
1629
    VarEnumerator_trail_top = (CPtr *)(& VarEnumerator_trail[0]) - 1;
 
1630
    ctr = attv_ctr = 0;
 
1631
 
 
1632
    switch (tag) {
 
1633
    case XSB_FREE: 
 
1634
    case XSB_REF1:
 
1635
      if (! IsStandardizedVariable(xtemp1)) {
 
1636
        StandardizeAndTrailVariable(xtemp1,ctr);
 
1637
        one_node_chk_ins(flag,EncodeNewTrieVar(ctr),
 
1638
                         INTERN_TRIE_TT);
 
1639
        ctr++;
 
1640
      } else {
 
1641
        one_node_chk_ins(flag,
 
1642
                         EncodeTrieVar(IndexOfStdVar(xtemp1)),
 
1643
                         INTERN_TRIE_TT);
 
1644
      }
 
1645
      break;
 
1646
    case XSB_STRING: 
 
1647
    case XSB_INT:
 
1648
    case XSB_FLOAT:
 
1649
      one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), INTERN_TRIE_TT);
 
1650
      break;
 
1651
    case XSB_LIST:
 
1652
      one_node_chk_ins(flag, EncodeTrieList(xtemp1), INTERN_TRIE_TT);
 
1653
      pdlpush(cell(clref_val(xtemp1)+1));
 
1654
      pdlpush(cell(clref_val(xtemp1)));
 
1655
      recvariant_trie(flag,INTERN_TRIE_TT);
 
1656
      break;
 
1657
    case XSB_STRUCT:
 
1658
      one_node_chk_ins(flag, makecs(follow(cs_val(xtemp1))),INTERN_TRIE_TT);
 
1659
      for (j = get_arity((Psc)follow(cs_val(xtemp1))); j >= 1 ; j--) {
 
1660
        pdlpush(cell(clref_val(xtemp1)+j));
 
1661
      }
 
1662
      recvariant_trie(flag,INTERN_TRIE_TT);
 
1663
      break;
 
1664
    case XSB_ATTV:
 
1665
      /* Now xtemp1 can only be the first occurrence of an attv */
 
1666
      xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
 
1667
      /*
 
1668
       * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
 
1669
       * later occurrences of this attv will look like a regular variable
 
1670
       * (after dereferencing).
 
1671
       */
 
1672
      StandardizeAndTrailVariable(xtemp1, ctr); 
 
1673
      one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), INTERN_TRIE_TT);
 
1674
      attv_ctr++; ctr++;
 
1675
      pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */
 
1676
      recvariant_trie(flag, INTERN_TRIE_TT);
 
1677
      break;
 
1678
    default:
 
1679
      xsb_abort("Bad type tag in whole_term_check_ins()");
 
1680
    }
 
1681
 
 
1682
    /*
 
1683
     *  If an insertion was performed, do some maintenance on the new leaf.
 
1684
     */
 
1685
    if ( flag == 0 ) {
 
1686
      MakeLeafNode(Paren);
 
1687
      TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
 
1688
    }
 
1689
 
 
1690
    /*
 
1691
     * var_regs[] is used to construct the last argument of trie_intern/5
 
1692
     * (Skel).  This is done in construct_ret(), which is called in
 
1693
     * get_lastnode_cs_retskel().
 
1694
     */
 
1695
    for (j = 0; j < ctr; j++) var_regs[j] = VarEnumerator_trail[j];
 
1696
    /*
 
1697
     * Both global_num_vars and Last_Nod_Sav are needed by
 
1698
     * get_lastnode_cs_retskel() (see trie_intern/5 in intern.P).
 
1699
     */
 
1700
    global_num_vars = num_vars_in_var_regs = ctr - 1;
 
1701
    Last_Nod_Sav = Paren;
 
1702
    simple_table_undo_bindings;
 
1703
 
 
1704
    /* if node was deleted, then return 0 to indicate that the insertion took
 
1705
       place conceptually (even if not physically */
 
1706
    if (IsDeletedNode(Paren)) {
 
1707
      *flagptr = 0;
 
1708
      undelete_branch(Paren);
 
1709
    } else
 
1710
      *flagptr = flag;
 
1711
 
 
1712
    return(Paren);
 
1713
}
 
1714
 
 
1715
/*----------------------------------------------------------------------*/
 
1716
/* one_term_chk_ins(termptr,hook,flag)                                  */
 
1717
/*----------------------------------------------------------------------*/
 
1718
 
 
1719
/*
 
1720
 * For creating asserted tries with builtin "trie_assert".
 
1721
 */
 
1722
 
 
1723
BTNptr one_term_chk_ins(CTXTdeclc CPtr termptr, BTNptr root, int *flagptr)
 
1724
{
 
1725
  int  arity;
 
1726
  CPtr cptr;
 
1727
  CPtr xtemp1;
 
1728
  int  i, j, flag = 1;
 
1729
  Cell tag = XSB_FREE, item;
 
1730
  Psc  psc;
 
1731
  int ctr, attv_ctr;
 
1732
  BTNptr Paren, *GNodePtrPtr;
 
1733
 
 
1734
  psc = term_psc((prolog_term)termptr);
 
1735
  arity = get_arity(psc);
 
1736
  cptr = (CPtr)cs_val(termptr);
 
1737
 
 
1738
  VarEnumerator_trail_top = (CPtr *)(& VarEnumerator_trail[0]) - 1;
 
1739
  ctr = attv_ctr = 0;
 
1740
  /*
 
1741
   * The value of `Paren' effects the "body" of the trie: nodes which
 
1742
   * are created the first level down get this value in their parent
 
1743
   * field.  This could be a problem when deleting trie paths, as this
 
1744
   * root needs to persist beyond the life of its body.
 
1745
   */
 
1746
  Paren = root;
 
1747
  GNodePtrPtr = &BTN_Child(root);
 
1748
  for (i = 1; i<=arity; i++) {
 
1749
    xtemp1 = (CPtr) (cptr + i);
 
1750
    XSB_CptrDeref(xtemp1);
 
1751
    tag = cell_tag(xtemp1);
 
1752
    switch (tag) {
 
1753
    case XSB_FREE: 
 
1754
    case XSB_REF1:
 
1755
      if (! IsStandardizedVariable(xtemp1)) {
 
1756
        StandardizeAndTrailVariable(xtemp1,ctr);
 
1757
        one_node_chk_ins(flag, EncodeNewTrieVar(ctr),
 
1758
                         ASSERT_TRIE_TT);
 
1759
        ctr++;
 
1760
      } else {
 
1761
        one_node_chk_ins(flag,
 
1762
                         EncodeTrieVar(IndexOfStdVar(xtemp1)),
 
1763
                         ASSERT_TRIE_TT);
 
1764
      }
 
1765
      break;
 
1766
    case XSB_STRING: 
 
1767
    case XSB_INT:
 
1768
    case XSB_FLOAT:
 
1769
      one_node_chk_ins(flag, EncodeTrieConstant(xtemp1), ASSERT_TRIE_TT);
 
1770
      break;
 
1771
    case XSB_LIST:
 
1772
      one_node_chk_ins(flag, EncodeTrieList(xtemp1), ASSERT_TRIE_TT);
 
1773
      pdlpush(cell(clref_val(xtemp1)+1));
 
1774
      pdlpush(cell(clref_val(xtemp1)));
 
1775
      recvariant_trie(flag,ASSERT_TRIE_TT);
 
1776
      break;
 
1777
    case XSB_STRUCT:
 
1778
      psc = (Psc) follow(cs_val(xtemp1));
 
1779
      one_node_chk_ins(flag, makecs(psc),ASSERT_TRIE_TT);
 
1780
      for (j = get_arity(psc); j >= 1 ; j--) {
 
1781
        pdlpush(cell(clref_val(xtemp1)+j));
 
1782
      }
 
1783
      recvariant_trie(flag,ASSERT_TRIE_TT);
 
1784
      break;
 
1785
    case XSB_ATTV:
 
1786
      /* Now xtemp1 can only be the first occurrence of an attv */
 
1787
      xtemp1 = clref_val(xtemp1); /* the VAR part of the attv */
 
1788
      /*
 
1789
       * Bind the VAR part of this attv to VarEnumerator[ctr], so all the
 
1790
       * later occurrences of this attv will look like a regular variable
 
1791
       * (after dereferencing).
 
1792
       */
 
1793
      StandardizeAndTrailVariable(xtemp1, ctr); 
 
1794
      one_node_chk_ins(flag, EncodeNewTrieAttv(ctr), ASSERT_TRIE_TT);
 
1795
      attv_ctr++; ctr++;
 
1796
      pdlpush(cell(xtemp1+1));  /* the ATTR part of the attv */
 
1797
      recvariant_trie(flag, ASSERT_TRIE_TT);
 
1798
      break;
 
1799
    default:
 
1800
      xsb_abort("Bad type tag in one_term_check_ins()");
 
1801
    }
 
1802
  }                
 
1803
  resetpdl;                                                   
 
1804
 
 
1805
  simple_table_undo_bindings;
 
1806
 
 
1807
  /* if there is no term to insert, an ESCAPE node has to be created/found */
 
1808
 
 
1809
  if (arity == 0) {
 
1810
    one_node_chk_ins(flag, ESCAPE_NODE_SYMBOL, ASSERT_TRIE_TT);
 
1811
    Instr(Paren) = trie_proceed;
 
1812
  }
 
1813
 
 
1814
  /*
 
1815
   *  If an insertion was performed, do some maintenance on the new leaf.
 
1816
   */
 
1817
  if ( flag == 0 ) {
 
1818
    MakeLeafNode(Paren);
 
1819
    TN_UpgradeInstrTypeToSUCCESS(Paren,tag);
 
1820
  }
 
1821
 
 
1822
  *flagptr = flag;      
 
1823
  return(Paren);
 
1824
}
 
1825
 
 
1826
/*----------------------------------------------------------------------*/
 
1827
 
 
1828
/*
 
1829
 * This is builtin #150: TRIE_GET_RETURN
 
1830
 */
 
1831
 
 
1832
byte *trie_get_returns(CTXTdeclc VariantSF sf, Cell retTerm) {
 
1833
 
 
1834
  BTNptr ans_root_ptr;
 
1835
  Cell retSymbol;
 
1836
#ifdef MULTI_THREAD_RWL
 
1837
   CPtr tbreg;
 
1838
#ifdef SLG_GC
 
1839
   CPtr old_cptop;
 
1840
#endif
 
1841
#endif
 
1842
 
 
1843
 
 
1844
#ifdef DEBUG_DELAYVAR
 
1845
  xsb_dbgmsg((LOG_DEBUG,">>>> (at the beginning of trie_get_returns"));
 
1846
  xsb_dbgmsg((LOG_DEBUG,">>>> num_vars_in_var_regs = %d)", num_vars_in_var_regs));
 
1847
#endif
 
1848
 
 
1849
  if ( IsProperlySubsumed(sf) )
 
1850
    ans_root_ptr = subg_ans_root_ptr(conssf_producer(sf));
 
1851
  else
 
1852
    ans_root_ptr = subg_ans_root_ptr(sf);
 
1853
  if ( IsNULL(ans_root_ptr) )
 
1854
    return (byte *)&fail_inst;
 
1855
 
 
1856
  if ( isconstr(retTerm) )
 
1857
    retSymbol = EncodeTrieFunctor(retTerm);  /* ret/n rep as XSB_STRUCT */
 
1858
  else
 
1859
    retSymbol = retTerm;   /* ret/0 would be represented as a XSB_STRING */
 
1860
  if ( retSymbol != BTN_Symbol(ans_root_ptr) )
 
1861
    return (byte *)&fail_inst;
 
1862
 
 
1863
  num_vars_in_var_regs = -1;
 
1864
  if ( isconstr(retTerm) ) {
 
1865
    int i, arity;
 
1866
    CPtr cptr;
 
1867
 
 
1868
    arity = get_arity(get_str_psc(retTerm));
 
1869
    /* Initialize var_regs[] as the attvs in the call. */
 
1870
    for (i = 0, cptr = clref_val(retTerm) + 1;  i < arity;  i++, cptr++) {
 
1871
      if (isattv(cell(cptr)))
 
1872
        var_regs[++num_vars_in_var_regs] = (CPtr) cell(cptr);
 
1873
    }
 
1874
    /* now num_vars_in_var_regs should be attv_num - 1 */
 
1875
 
 
1876
    reg_arrayptr = reg_array -1;
 
1877
    for (i = arity, cptr = clref_val(retTerm);  i >= 1;  i--) {
 
1878
      pushreg(cell(cptr+i));
 
1879
    }
 
1880
  }
 
1881
#ifdef DEBUG_DELAYVAR
 
1882
  xsb_dbgmsg((LOG_DEBUG,">>>> The end of trie_get_returns ==> go to answer trie"));
 
1883
#endif
 
1884
  delay_it = 0;  /* Don't delay the answer. */
 
1885
#ifdef MULTI_THREAD_RWL
 
1886
/* save choice point for trie_unlock instruction */
 
1887
       save_find_locx(ereg);
 
1888
       tbreg = top_of_cpstack;
 
1889
#ifdef SLG_GC
 
1890
       old_cptop = tbreg;
 
1891
#endif
 
1892
       save_choicepoint(tbreg,ereg,(byte *)&trie_fail_unlock_inst,breg);
 
1893
#ifdef SLG_GC
 
1894
       cp_prevtop(tbreg) = old_cptop;
 
1895
#endif
 
1896
       breg = tbreg;
 
1897
       hbreg = hreg;
 
1898
#endif
 
1899
  return (byte *)ans_root_ptr;
 
1900
}
 
1901
 
 
1902
/*----------------------------------------------------------------------*/
 
1903
 
 
1904
byte * trie_get_calls(CTXTdecl)
 
1905
{
 
1906
   Cell call_term;
 
1907
   Psc psc_ptr;
 
1908
   TIFptr tip_ptr;
 
1909
   BTNptr call_trie_root;
 
1910
   CPtr cptr;
 
1911
   int i;
 
1912
#ifdef MULTI_THREAD_RWL
 
1913
   CPtr tbreg;
 
1914
#ifdef SLG_GC
 
1915
   CPtr old_cptop;
 
1916
#endif
 
1917
#endif
 
1918
 
 
1919
   call_term = ptoc_tag(CTXTc 1);
 
1920
   if ((psc_ptr = term_psc(call_term)) != NULL) {
 
1921
     tip_ptr = get_tip(CTXTc psc_ptr);
 
1922
     if (tip_ptr == NULL) {
 
1923
       xsb_abort("get_calls/3 called with non-tabled predicate");
 
1924
       return (byte *)&fail_inst;
 
1925
     }
 
1926
     call_trie_root = TIF_CallTrie(tip_ptr);
 
1927
     if (call_trie_root == NULL)
 
1928
       return (byte *)&fail_inst;
 
1929
     else {
 
1930
       cptr = (CPtr)cs_val(call_term);
 
1931
       reg_arrayptr = reg_array-1;
 
1932
       num_vars_in_var_regs = -1;
 
1933
       for (i = get_arity(psc_ptr); i>=1; i--) {
 
1934
#ifdef DEBUG_DELAYVAR
 
1935
         xsb_dbgmsg((LOG_DEBUG,">>>> push one cell"));
 
1936
#endif
 
1937
         pushreg(cell(cptr+i));
 
1938
       }
 
1939
#ifdef MULTI_THREAD_RWL
 
1940
/* save choice point for trie_unlock instruction */
 
1941
       save_find_locx(ereg);
 
1942
       tbreg = top_of_cpstack;
 
1943
#ifdef SLG_GC
 
1944
       old_cptop = tbreg;
 
1945
#endif
 
1946
       save_choicepoint(tbreg,ereg,(byte *)&trie_fail_unlock_inst,breg);
 
1947
#ifdef SLG_GC
 
1948
       cp_prevtop(tbreg) = old_cptop;
 
1949
#endif
 
1950
       breg = tbreg;
 
1951
       hbreg = hreg;
 
1952
#endif
 
1953
 
 
1954
       return (byte *)call_trie_root;
 
1955
     }
 
1956
   }
 
1957
   else
 
1958
     return (byte *)&fail_inst;
 
1959
}
 
1960
 
 
1961
/*----------------------------------------------------------------------*/
 
1962
 
 
1963
/*
 
1964
 * This function is changed from get_lastnode_and_retskel().  It is the
 
1965
 * body of *inline* builtin GET_LASTNODE_CS_RETSKEL(LastNode, CallStr,
 
1966
 * RetSkel). [1/9/1999]
 
1967
 *
 
1968
 * This function is called immediately after using the trie intructions
 
1969
 * to traverse one branch of the call or answer trie.  A side-effect of
 
1970
 * executing these instructions is that the leaf node of the branch is
 
1971
 * left in a global variable "Last_Nod_Sav".  One reason for writing it
 
1972
 * so is that it is important that the construction of the return
 
1973
 * skeleton is an operation that cannot be interrupted by garbage
 
1974
 * collection.
 
1975
 *
 
1976
 * In case we just traversed the Call Trie of a subsumptive predicate,
 
1977
 * and the call we just unified with is subsumed, then the answer
 
1978
 * template (i.e., the return) must be reconstructed based on the
 
1979
 * original call, the argument "callTerm" below, and the subsuming call
 
1980
 * in the table.  Otherwise, we return the variables placed in
 
1981
 * "var_regs[]" during the embedded-trie-code walk.
 
1982
 */
 
1983
Cell get_lastnode_cs_retskel(CTXTdeclc Cell callTerm) {
 
1984
 
 
1985
  int arity;
 
1986
  Cell *vector;
 
1987
 
 
1988
  arity = global_num_vars + 1;
 
1989
  vector = (Cell *)var_regs;
 
1990
  if ( IsInCallTrie(Last_Nod_Sav) ) {
 
1991
    VariantSF sf = CallTrieLeaf_GetSF(Last_Nod_Sav);
 
1992
    if ( IsProperlySubsumed(sf) ) {
 
1993
      construct_answer_template(CTXTc callTerm, conssf_producer(sf),
 
1994
                                (Cell *)var_regs);
 
1995
      arity = (int)var_regs[0];
 
1996
      vector = (Cell *)&var_regs[1];
 
1997
    }
 
1998
  }
 
1999
  return ( build_ret_term(CTXTc arity, vector) );
 
2000
}
 
2001
 
 
2002
/*----------------------------------------------------------------------*/
 
2003
/* creates an empty (dummy) answer.                                     */
 
2004
/*----------------------------------------------------------------------*/
 
2005
 
 
2006
ALNptr empty_return(CTXTdeclc VariantSF subgoal)
 
2007
{
 
2008
    ALNptr i;
 
2009
  
 
2010
    /* Used only in one context hence this abuse */
 
2011
    New_ALN(subgoal,i,&dummy_ans_node,NULL);
 
2012
    return i;
 
2013
}
 
2014
 
 
2015
/*----------------------------------------------------------------------*/