1 /*************************************************************************
2 *									 *
3 *	 YAP Prolog 	%W% %G%		*
4 *									 *
5 *	Yap Prolog was developed at NCCUP - Universidade do Porto	 *
6 *									 *
7 * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997	 *
8 *									 *
9 **************************************************************************
10 *									 *
11 * File:		clause.h						 *
12 * Last rev:								 *
13 * mods:									 *
14 * comments:	clause info						 *
15 *									 *
16 *************************************************************************/
17 
18 #include "Yatom.h"
19 #include "YapHeap.h"
20 
21 /* consulting files */
22 
23 typedef union CONSULT_OBJ {
24   char *filename;
25   int mode;
26   Prop  p;
27   UInt c;
28 } consult_obj;
29 
30 /* Either we are assembling clauses or indexing code */
31 
32 #define ASSEMBLING_CLAUSE	0
33 #define ASSEMBLING_INDEX	1
34 #define ASSEMBLING_EINDEX	2
35 
36 #define NextDynamicClause(X)	(((yamop *)X)->u.Otapl.d)
37 
38 #define PredFirstClause		0
39 #define PredMiddleClause	1
40 #define PredLastClause		2
41 
42 typedef struct logic_upd_index {
43   CELL             ClFlags;
44   UInt             ClRefCount;
45 #if defined(YAPOR) || defined(THREADS)
46   /* A lock for manipulating the clause */
47   //  lockvar          ClLock;
48 #endif
49   UInt		   ClSize;
50   struct logic_upd_index *ParentIndex;
51   struct logic_upd_index *SiblingIndex;
52   struct logic_upd_index *PrevSiblingIndex;
53   struct logic_upd_index *ChildIndex;
54   /* The instructions, at least one of the form sl */
55   PredEntry *ClPred;
56   yamop            ClCode[MIN_ARRAY];
57 } LogUpdIndex;
58 
59 /* The ordering of the first 3 fields should be compatible with dbrefs */
60 typedef struct logic_upd_clause {
61   Functor Id;		/* allow pointers to this struct to id  */
62 			/*   as dbref                           */
63   /* A set of flags describing info on the clause */
64   /* A set of flags describing info on the clause */
65   CELL             ClFlags;
66 #if defined(YAPOR) || defined(THREADS)
67   /* A lock for manipulating the clause */
68   //  lockvar          ClLock;
69 #endif
70   UInt		  ClSize;
71   /* extra clause information for logical update indices and facts */
72   /* indices that may still backtrack to this clause */
73   UInt             ClRefCount;
74   /* data for clauses  with environments */
75   yamop           *ClExt;
76   DBTerm          *ClSource;
77   /* doubly linked list of clauses */
78   struct logic_upd_clause   *ClPrev, *ClNext;
79   /* parent pointer */
80   PredEntry   *ClPred;
81   UInt             ClTimeStart, ClTimeEnd;
82   /* The instructions, at least one of the form sl */
83   yamop            ClCode[MIN_ARRAY];
84 } LogUpdClause;
85 
86 inline EXTERN int VALID_TIMESTAMP(UInt, struct logic_upd_clause *);
87 
88 inline EXTERN int
VALID_TIMESTAMP(UInt timestamp,struct logic_upd_clause * cl)89 VALID_TIMESTAMP(UInt timestamp, struct logic_upd_clause *cl)
90 {
91   return IN_BETWEEN(cl->ClTimeStart, timestamp, cl->ClTimeEnd);
92 }
93 
94 typedef struct dynamic_clause {
95   /* A set of flags describing info on the clause */
96   CELL            ClFlags;
97 #if defined(YAPOR) || defined(THREADS)
98   /* A lock for manipulating the clause */
99   lockvar          ClLock;
100 #endif
101   UInt		   ClSize;
102   UInt             ClRefCount;
103   yamop              *ClPrevious;     /* immediate update clause */
104   /* The instructions, at least one of the form sl */
105   yamop            ClCode[MIN_ARRAY];
106 } DynamicClause;
107 
108 typedef struct static_index {
109   /* A set of flags describing info on the clause */
110   CELL            ClFlags;
111   UInt		  ClSize;
112   struct static_index *SiblingIndex;
113   struct static_index *ChildIndex;
114   /* The instructions, at least one of the form sl */
115   PredEntry *ClPred;
116   yamop            ClCode[MIN_ARRAY];
117 } StaticIndex;
118 
119 typedef struct static_clause {
120   /* A set of flags describing info on the clause */
121   CELL            ClFlags;
122   UInt		  ClSize;
123   union {
124     DBTerm          *ClSource;
125     PredEntry       *ClPred;
126   } usc;
127   struct static_clause   *ClNext;
128   /* The instructions, at least one of the form sl */
129   yamop            ClCode[MIN_ARRAY];
130 } StaticClause;
131 
132 typedef struct static_mega_clause {
133   /* A set of flags describing info on the clause */
134   CELL            ClFlags;
135   UInt		  ClSize;
136   PredEntry      *ClPred;
137   UInt            ClItemSize;
138   struct  static_mega_clause *ClNext;
139   /* The instructions, at least one of the form sl */
140   yamop            ClCode[MIN_ARRAY];
141 } MegaClause;
142 
143 typedef union clause_obj {
144   struct logic_upd_clause luc;
145   struct logic_upd_index lui;
146   struct dynamic_clause ic;
147   struct static_clause sc;
148   struct static_mega_clause mc;
149   struct static_index si;
150 } ClauseUnion;
151 
152 typedef union clause_ptr {
153   struct logic_upd_clause *luc;
154   struct logic_upd_index *lui;
155   struct dynamic_clause *ic;
156   struct static_clause *sc;
157   struct static_mega_clause *mc;
158   struct static_index *si;
159 } ClausePointer;
160 
161 typedef struct dbterm_list {
162   /* a list of dbterms associated with a clause */
163   DBTerm *dbterms;
164   yamop *clause_code;
165   PredEntry *p;
166   struct dbterm_list *next_dbl;
167 } DBTermList;
168 
169 #define ClauseCodeToDynamicClause(p)    ((DynamicClause *)((CODEADDR)(p)-(CELL)(((DynamicClause *)NULL)->ClCode)))
170 #define ClauseCodeToStaticClause(p)    ((StaticClause *)((CODEADDR)(p)-(CELL)(((StaticClause *)NULL)->ClCode)))
171 #define ClauseCodeToLogUpdClause(p)    ((LogUpdClause *)((CODEADDR)(p)-(CELL)(((LogUpdClause *)NULL)->ClCode)))
172 #define ClauseCodeToMegaClause(p)    ((MegaClause *)((CODEADDR)(p)-(CELL)(((MegaClause *)NULL)->ClCode)))
173 #define ClauseCodeToLogUpdIndex(p)    ((LogUpdIndex *)((CODEADDR)(p)-(CELL)(((LogUpdIndex *)NULL)->ClCode)))
174 #define ClauseCodeToStaticIndex(p)    ((StaticIndex *)((CODEADDR)(p)-(CELL)(((StaticIndex *)NULL)->ClCode)))
175 
176 #define ClauseFlagsToDynamicClause(p)    ((DynamicClause *)(p))
177 #define ClauseFlagsToLogUpdClause(p)     ((LogUpdClause *)((CODEADDR)(p)-(CELL)(&(((LogUpdClause *)NULL)->ClFlags))))
178 #define ClauseFlagsToLogUpdIndex(p)      ((LogUpdIndex *)((CODEADDR)(p)-(CELL)(&(((LogUpdIndex *)NULL)->ClFlags))))
179 #define ClauseFlagsToStaticClause(p)     ((StaticClause *)(p))
180 
181 #define DynamicFlags(X)		(ClauseCodeToDynamicClause(X)->ClFlags)
182 
183 #define DynamicLock(X)		(ClauseCodeToDynamicClause(X)->ClLock)
184 
185 #if defined(YAPOR) || defined(THREADS)
186 #define INIT_CLREF_COUNT(X) (X)->ClRefCount = 0
187 #define  INC_CLREF_COUNT(X) (X)->ClRefCount++
188 #define  DEC_CLREF_COUNT(X) (X)->ClRefCount--
189 
190 #define        CL_IN_USE(X) ((X)->ClRefCount)
191 #else
192 #define INIT_CLREF_COUNT(X)
193 #define  INC_CLREF_COUNT(X)
194 #define  DEC_CLREF_COUNT(X)
195 #define        CL_IN_USE(X) ((X)->ClFlags & InUseMask || (X)->ClRefCount)
196 #endif
197 
198 /* amasm.c */
199 wamreg	STD_PROTO(Yap_emit_x,(CELL));
200 COUNT   STD_PROTO(Yap_compile_cmp_flags,(PredEntry *));
201 void    STD_PROTO(Yap_InitComma,(void));
202 
203 /* cdmgr.c */
204 void	STD_PROTO(Yap_IPred,(PredEntry *, UInt, yamop *));
205 int	STD_PROTO(Yap_addclause,(Term,yamop *,int,Term,Term*));
206 void	STD_PROTO(Yap_add_logupd_clause,(PredEntry *,LogUpdClause *,int));
207 void	STD_PROTO(Yap_kill_iblock,(ClauseUnion *,ClauseUnion *,PredEntry *));
208 void	STD_PROTO(Yap_EraseStaticClause,(StaticClause *, Term));
209 ClauseUnion *STD_PROTO(Yap_find_owner_index,(yamop *, PredEntry *));
210 
211 /* dbase.c */
212 void	STD_PROTO(Yap_ErCl,(DynamicClause *));
213 void	STD_PROTO(Yap_ErLogUpdCl,(LogUpdClause *));
214 void    STD_PROTO(Yap_ErLogUpdIndex,(LogUpdIndex *));
215 Int	STD_PROTO(Yap_Recordz,(Atom, Term));
216 
217 /* exec.c */
218 Term    STD_PROTO(Yap_cp_as_integer,(choiceptr));
219 
220 /* index.c */
221 yamop   *STD_PROTO(Yap_PredIsIndexable,(PredEntry *, UInt, yamop *));
222 yamop   *STD_PROTO(Yap_ExpandIndex,(PredEntry *, UInt));
223 void     STD_PROTO(Yap_CleanUpIndex,(struct logic_upd_index *));
224 void     STD_PROTO(Yap_CleanKids,(struct logic_upd_index *));
225 void     STD_PROTO(Yap_AddClauseToIndex,(PredEntry *,yamop *,int));
226 void     STD_PROTO(Yap_RemoveClauseFromIndex,(PredEntry *,yamop *));
227 LogUpdClause  *STD_PROTO(Yap_NthClause,(PredEntry *,Int));
228 LogUpdClause  *STD_PROTO(Yap_FollowIndexingCode,(PredEntry *,yamop *, Term *, yamop *,yamop *));
229 
230 #if USE_THREADED_CODE
231 
232 #define OP_HASH_SIZE 2048
233 
234 static inline int
rtable_hash_op(OPCODE opc,int hash_mask)235 rtable_hash_op(OPCODE opc, int hash_mask) {
236   return((((CELL)opc) >> 3) & hash_mask);
237 }
238 
239 /* given an opcode find the corresponding opnumber. This should make
240    switches on ops a much easier operation */
241 static inline op_numbers
Yap_op_from_opcode(OPCODE opc)242 Yap_op_from_opcode(OPCODE opc)
243 {
244   int j = rtable_hash_op(opc,OP_HASH_SIZE-1);
245 
246   while (OP_RTABLE[j].opc != opc) {
247     if (!OP_RTABLE[j].opc)
248       return _Nstop;
249     if (j == OP_HASH_SIZE-1) {
250       j = 0;
251     } else {
252       j++;
253     }
254   }
255   return OP_RTABLE[j].opnum;
256 }
257 #else
258 static inline op_numbers
Yap_op_from_opcode(OPCODE opc)259 Yap_op_from_opcode(OPCODE opc)
260 {
261   return((op_numbers)opc);
262 }
263 #endif /* USE_THREADED_CODE */
264 
265 #if defined(YAPOR) || defined(THREADS)
266 static inline int same_lu_block(yamop **, yamop *);
267 
268 static inline int
same_lu_block(yamop ** paddr,yamop * p)269 same_lu_block(yamop **paddr, yamop *p)
270 {
271   yamop *np = *paddr;
272   if (np != p) {
273     OPCODE jmp_op = Yap_opcode(_jump_if_nonvar);
274 
275     while (np->opc == jmp_op) {
276       np = NEXTOP(np, xll);
277       if (np == p) return TRUE;
278     }
279     return FALSE;
280   } else {
281     return TRUE;
282   }
283 }
284 #endif
285 
286 static inline Term
Yap_MkStaticRefTerm(StaticClause * cp)287 Yap_MkStaticRefTerm(StaticClause *cp)
288 {
289   Term t[1];
290   t[0] = MkIntegerTerm((Int)cp);
291   return Yap_MkApplTerm(FunctorStaticClause,1,t);
292 }
293 
294 static inline StaticClause *
Yap_ClauseFromTerm(Term t)295 Yap_ClauseFromTerm(Term t)
296 {
297   return (StaticClause *)IntegerOfTerm(ArgOfTerm(1,t));
298 }
299 
300 static inline Term
Yap_MkMegaRefTerm(PredEntry * ap,yamop * ipc)301 Yap_MkMegaRefTerm(PredEntry *ap,yamop *ipc)
302 {
303   Term t[2];
304   t[0] = MkIntegerTerm((Int)ap);
305   t[1] = MkIntegerTerm((Int)ipc);
306   return Yap_MkApplTerm(FunctorMegaClause,2,t);
307 }
308 
309 static inline yamop *
Yap_MegaClauseFromTerm(Term t)310 Yap_MegaClauseFromTerm(Term t)
311 {
312   return (yamop *)IntegerOfTerm(ArgOfTerm(2,t));
313 }
314 
315 static inline PredEntry *
Yap_MegaClausePredicateFromTerm(Term t)316 Yap_MegaClausePredicateFromTerm(Term t)
317 {
318   return (PredEntry *)IntegerOfTerm(ArgOfTerm(1,t));
319 }
320 
321 typedef enum {
322   FIND_PRED_FROM_ANYWHERE,
323   FIND_PRED_FROM_CP,
324   FIND_PRED_FROM_ENV
325 } find_pred_type;
326 
327 Int	        STD_PROTO(Yap_PredForCode,(yamop *, find_pred_type, Atom *, UInt *, Term *));
328 PredEntry *STD_PROTO(Yap_PredEntryForCode,(yamop *, find_pred_type, CODEADDR *, CODEADDR *));
329 LogUpdClause   *STD_PROTO(Yap_new_ludbe,(Term, PredEntry *, UInt));
330 Term            STD_PROTO(Yap_LUInstance,(LogUpdClause *, UInt));
331 
332 /* udi.c */
333 void         STD_PROTO(Yap_udi_init,(void));
334 yamop       *STD_PROTO(Yap_udi_search,(PredEntry *));
335 int          STD_PROTO(Yap_new_udi_clause,(PredEntry *, yamop *, Term));
336 
337 #ifdef DEBUG
338 void    STD_PROTO(Yap_bug_location,(yamop *));
339 #endif
340 
341 #if  LOW_PROF
342 void	STD_PROTO(Yap_InformOfRemoval,(CODEADDR));
343 void	STD_PROTO(Yap_dump_code_area_for_profiler,(void));
344 #else
345 #define	Yap_InformOfRemoval(X)
346 #endif
347