Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
symtab.h
Go to the documentation of this file.
1 /*************************************************************************
2  * PLEASE SEE THE FILE "license.txt" (INCLUDED WITH THIS SOFTWARE PACKAGE)
3  * FOR LICENSE AND COPYRIGHT INFORMATION.
4  *************************************************************************/
5 
6 /* =======================================================================
7  symtab.h
8 
9  Soar 6 uses five kinds of symbols: symbolic constants, integer
10  constants, floating-point constants, identifiers, and variables.
11  We use five resizable hash tables, one for each kind of symbol.
12 
13  "symbol" is typedef-ed as a union of the five kinds of symbol
14  structures. Some fields common to all symbols are accessed via
15  sym->common.field_name; fields particular to a certain kind of
16  symbol are accessed via sym->var.field_name_on_variables, etc.
17  (See the definitions below.) Note that "common" is #defined below.
18 
19  Some (but not all) of the fields common to all symbols are:
20  symbol_type: indicates which of the five kinds of symbols this is
21  reference_count: current reference count for this symbol
22  hash_id: used for hash functions in the rete (and elsewhere)
23 
24  Fields on symbolic constants:
25  name: points to null-terminated string giving its name
26  production: points to a production structure, or NIL if there is
27  no production with that name
28 
29  Fields on integer constants:
30  value: gives the value of the symbol. This is of type (int64_t).
31 
32  Fields on floating-point constants:
33  value: gives the value of the symbol. This is of type (float).
34 
35  Fields on variables:
36  name: points to null-terminated string giving its name
37  tc_num: used for transitive closure computations
38  current_binding_value: when productions are fired, this indicates
39  the variable's binding
40  gensym_number: used by the variable generator to prevent certain
41  already-in-use variables from being generated
42  rete_binding_locations: used temporarily by the Rete, while adding
43  productions, to store a list of places where this
44  variable is bound and/or tested
45 
46  Fields on identifiers:
47 
48  name_number, name_letter: indicate the name of the identifier
49 
50  isa_goal, isa_impasse: indicate whether this is the identifier of a
51  goal or attribute impasse
52 
53  isa_operator: keeps a count of how many (normal or acceptable
54  preference) wmes contain (^operator <this-id>).
55  The tracing code uses this to figure out whether
56  a given object is an operator.
57 
58  allow_bottom_up_chunks: Used for bottom-up chunking, and only on goal
59  identifiers. This is TRUE iff no chunk has yet been built for a
60  subgoal of this goal.
61 
62  could_be_a_link_from_below: TRUE if there might be a link to this id
63  from some other id lower in the goal stack.
64 
65  did_PE:
66 
67  level: current goal_stack_level of this id
68 
69  promotion_level: level to which this id is going to be promoted as
70  soon as ownership info is updated.
71 
72  link_count: count of how many links there are to this id.
73 
74  unknown_level: if the goal_stack_level of this id is known, this is
75  NIL. If the level isn't known, it points to a dl_cons in a dl_list
76  used by the demotion routines.
77 
78  slots: this is the header for a dll of the slots for this id.
79 
80  tc_num: used for transitive closures, marking id's, etc.
81 
82  variablization: used by the chunker when variablizing chunks--this
83  points to the variable to which this id gets changed
84 
85  impasse_wmes: for goal and impasse ids only: this is the header
86  of the dll of architecture-created wmes (e.g., (G37 ^object G36))
87 
88  higher_goal, lower_goal: for goals, these point to adjacent goals
89  in the context stack
90  problem_space_slot, state_slot, operator_slot: for goals, these
91  point to the corresponding context slots
92  preferences_from_goal: for goals, this is the header of the dll
93  of all preferences supported by this goal. This is needed so
94  we can remove o-supported preferences when the goal goes away.
95 
96  gds: pointer to a goal's dependency set
97  saved_firing_type: the firing type that must be restored if
98  Waterfall processing returns to this level. see consistency.c
99  ms_o_assertions: dll of o-assertions at this level
100  ms_i_assertions: dll of i-assertions at this level
101  ms_retractions: dll of all retractions at this level
102 
103  associated_output_links: used by the output module
104 
105  input_wmes: dll of wmes added by input functions
106 
107  Reference counting for symbols: I can't remember all the places I add
108  reference counts to symbols. Here's a bunch I can remember though.
109  If you're not sure whether to add/remove a reference for something,
110  it's better to play it safe and do the add/remove.
111 
112  +1 for each occurrence in a rete test or alpha mem constant test
113  +1 for each occurrence in a condition test anywhere
114  +1 for each occurrence in a Not
115  +1 for each occurrence in a saved_test
116  +1 for each occurrence in a WME
117  +1 for each occurrence in a preference
118  +1 for each occurrence as {id or attr} of a slot
119  +1 for goal/impasse identifiers
120  +1 if it's the name of a production
121  +1 if it's a predefined symbol (e.g., "goal" or "operator")
122  +1 for each enqueued add-link or remove-link to/from it
123  +1 for each occurrence in a global var. (e.g., chunk-free-problem-spaces)
124 
125  We deallocate a symbol when its reference count goes to 0.
126 ======================================================================= */
127 
128 #include "kernel.h"
129 
130 #ifndef SYMTAB_H
131 #define SYMTAB_H
132 
133 #ifdef __cplusplus
134 //extern "C"
135 //{
136 #endif
137 
138 #define VARIABLE_SYMBOL_TYPE 0
139 #define IDENTIFIER_SYMBOL_TYPE 1
140 #define SYM_CONSTANT_SYMBOL_TYPE 2
141 #define INT_CONSTANT_SYMBOL_TYPE 3
142 #define FLOAT_CONSTANT_SYMBOL_TYPE 4
143 
144 typedef char Bool;
145 typedef unsigned char byte;
146 typedef uint64_t tc_number;
147 typedef signed short goal_stack_level;
148 typedef struct cons_struct cons;
149 typedef struct agent_struct agent;
150 typedef struct dl_cons_struct dl_cons;
151 typedef cons list;
152 
153 typedef int64_t epmem_node_id;
154 typedef uint64_t epmem_hash_id;
155 typedef uint64_t epmem_time_id;
156 typedef uint64_t smem_lti_id;
157 typedef uint64_t smem_hash_id;
158 
159 /* WARNING: In the following structure, next_in_hash_table MUST be the
160  first field. This field is used by the resizable hash table routines. */
161 
163  union symbol_union *next_in_hash_table; /* next item in hash bucket */
164  uint64_t reference_count;
165  byte symbol_type; /* one of the above xxx_SYMBOL_TYPE's */
166  byte decider_flag; /* used only by the decider */
167  union a_union {
168  struct wme_struct *decider_wme; /* used only by the decider */
169  uint64_t retesave_symindex; /* used for rete fastsave/fastload */
170  } a;
171  uint32_t hash_id; /* used for hashing in the rete */
172 
174  uint64_t epmem_valid;
175 
177  uint64_t smem_valid;
179 
180 /* WARNING: In the following structures (the five kinds of symbols),
181  common_symbol_info MUST be the first field. */
182 
183 typedef struct sym_constant_struct {
185  char *name;
186  struct production_struct *production; /* NIL if no prod. has this name */
187 } sym_constant;
188 
189 typedef struct int_constant_struct {
191  int64_t value;
192 } int_constant;
193 
194 typedef struct float_constant_struct {
196  double value;
198 
199 typedef struct variable_struct {
201  char *name;
204  uint64_t gensym_number;
206 } variable;
207 
208 /* Note: I arranged the fields below to try to minimize space */
209 typedef struct identifier_struct {
211  uint64_t name_number;
213 
214  Bool isa_goal; /* TRUE iff this is a goal identifier */
215  Bool isa_impasse; /* TRUE iff this is an attr. impasse identifier */
216 
217  Bool did_PE; /* RCHONG: 10.11 */
218 
219  unsigned short isa_operator;
220 
222 
223  /* --- ownership, promotion, demotion, & garbage collection stuff --- */
227  uint64_t link_count;
229 
230  struct slot_struct *slots; /* dll of slots for this identifier */
231  tc_number tc_num; /* used for transitive closures, marking, etc. */
232  union symbol_union *variablization; /* used by the chunker */
233 
234  /* --- fields used only on goals and impasse identifiers --- */
236 
237  /* --- fields used only on goals --- */
241 
242  union symbol_union *reward_header; // pointer to reward_link
243  struct rl_data_struct *rl_info; // various Soar-RL information
244 
249  struct epmem_data_struct *epmem_info; // various EpMem information
250 
251 
255  struct smem_data_struct *smem_info; // various SMem information
256 
257 
258  /* REW: begin 09.15.96 */
259  struct gds_struct *gds; /* Pointer to a goal's dependency set */
260  /* REW: begin 09.15.96 */
261 
262  /* REW: begin 08.20.97 */
263  int saved_firing_type; /* FIRING_TYPE that must be restored if Waterfall
264  processing returns to this level.
265  See consistency.cpp */
266  struct ms_change_struct *ms_o_assertions; /* dll of o assertions at this level */
267  struct ms_change_struct *ms_i_assertions; /* dll of i assertions at this level */
268  struct ms_change_struct *ms_retractions; /* dll of retractions at this level */
269  /* REW: end 08.2097 */
270 
271  /* --- fields used for Soar I/O stuff --- */
274 
275  int depth; /* used to track depth of print (bug 988) RPM 4/07 */
276 
278  uint64_t epmem_valid;
279 
282  uint64_t smem_valid;
283 } identifier;
284 
285 typedef union symbol_union {
291 } Symbol;
292 
293 /* WARNING: this #define's "common". Don't use "common" anywhere in the
294  code unless you intend this meaning of it. This is so we can
295  conveniently access fields used in all kinds of symbols, like this:
296  "sym.common.reference_count" rather than "sym.var.common.reference_count"
297  or "sym.id.common.reference_count", etc. */
298 
299 #define common var.common_symbol_info
300 
301 /* -----------------------------------------------------------------
302  Symbol Table Routines
303 
304  Initialization:
305 
306  Init_symbol_tables() should be called first, to initialize the
307  module.
308 
309  Lookup and Creation:
310 
311  The find_xxx() routines look for an existing symbol and return it
312  if found; if no such symbol exists, they return NIL.
313 
314  The make_xxx() routines look for an existing symbol; if the find one,
315  they increment the reference count and return it. If no such symbol
316  exists, they create a new one, set the reference count to 1, and
317  return it.
318 
319  Note that rather than a make_identifier() routine, we have a
320  make_new_identifier() routine, which takes two arguments: the first
321  letter for the new identifier, and its initial goal_stack_level.
322  There is no way to force creation of an identifier with a particular
323  name letter/number combination like J37.
324 
325  Reference Counting:
326 
327  Symbol_add_ref() and symbol_remove_ref() are macros for incrementing
328  and decrementing the reference count on a symbol. When the count
329  goes to zero, symbol_remove_ref() calls deallocate_symbol().
330 
331  Other Utilities:
332 
333  Reset_id_counters() is called during an init-soar to reset the id
334  gensym numbers to 1. It first makes sure there are no existing
335  identifiers in the system--otherwise we might generate a second
336  identifier with the same name later on.
337 
338  Reset_id_and_variable_tc_numbers() resets the tc_num field of every
339  existing id and variable to 0.
340 
341  Reset_variable_gensym_numbers() resets the gensym_number field of
342  every existing variable to 0.
343 
344  Print_internal_symbols() just prints a list of all existing symbols.
345  (This is useful for debugging memory leaks.)
346 
347  Generate_new_sym_constant() is used to gensym new symbols that are
348  guaranteed to not already exist. It takes two arguments: "prefix"
349  (the desired prefix of the new symbol's name), and "counter" (a
350  pointer to a counter (uint64_t) that is incremented to produce
351  new gensym names).
352 ----------------------------------------------------------------- */
353 
354 extern void init_symbol_tables (agent* thisAgent);
355 
356 extern Symbol *find_variable (agent* thisAgent, const char *name);
357 extern Symbol *find_identifier (agent* thisAgent, char name_letter, uint64_t name_number);
358 extern Symbol *find_sym_constant (agent* thisAgent, const char *name); /* AGR 600 */
359 extern Symbol *find_int_constant (agent* thisAgent, int64_t value);
360 extern Symbol *find_float_constant (agent* thisAgent, double value);
361 
362 extern Symbol *make_variable (agent* thisAgent, const char *name);
363 extern Symbol *make_sym_constant (agent* thisAgent, char const *name);
364 extern Symbol *make_int_constant (agent* thisAgent, int64_t value);
365 extern Symbol *make_float_constant (agent* thisAgent, double value);
366 extern Symbol *make_new_identifier (agent* thisAgent, char name_letter, goal_stack_level level, uint64_t name_number = NIL);
367 
368 extern void deallocate_symbol (agent* thisAgent, Symbol *sym);
369 
370 extern bool reset_id_counters (agent* thisAgent);
371 extern void reset_id_and_variable_tc_numbers (agent* thisAgent);
372 extern void reset_variable_gensym_numbers (agent* thisAgent);
373 extern void print_internal_symbols (agent* thisAgent);
374 extern Symbol *generate_new_sym_constant (agent* thisAgent, const char *prefix, uint64_t *counter);
375 
376 #ifdef USE_MACROS
377 
378 /* --- macros used for changing the reference count --- */
379 #define symbol_add_ref(x) {(x)->common.reference_count++;}
380 #define symbol_remove_ref(thisAgent, x) { \
381  (x)->common.reference_count--; \
382  if ((x)->common.reference_count == 0) \
383  deallocate_symbol(thisAgent, x); \
384  }
385 
386 #else
387 
388 #ifdef DEBUG_SYMBOL_REFCOUNTS
389 extern char *symbol_to_string (agent* thisAgent, Symbol *sym, Bool rereadable, char *dest, size_t dest_size);
390 #endif
391 
392 inline uint64_t symbol_add_ref(Symbol * x)
393 {
394  (x)->common.reference_count++;
395  uint64_t refCount = (x)->common.reference_count ;
396 #ifdef DEBUG_SYMBOL_REFCOUNTS
397  char buf[64];
398  OutputDebugString(symbol_to_string(0, x, FALSE, buf, 64));
399  OutputDebugString(":+ ");
400  OutputDebugString(_itoa(refCount, buf, 10));
401  OutputDebugString("\n");
402 #endif // DEBUG_SYMBOL_REFCOUNTS
403  return refCount ;
404 }
405 
406 inline uint64_t symbol_remove_ref(agent* thisAgent, Symbol * x)
407 {
408  (x)->common.reference_count--;
409  uint64_t refCount = (x)->common.reference_count ;
410 #ifdef DEBUG_SYMBOL_REFCOUNTS
411  char buf[64];
412  OutputDebugString(symbol_to_string(thisAgent, x, FALSE, buf, 64));
413  OutputDebugString(":- ");
414  OutputDebugString(_itoa(refCount, buf, 10));
415  OutputDebugString("\n");
416 #endif // DEBUG_SYMBOL_REFCOUNTS
417  if ((x)->common.reference_count == 0)
418  deallocate_symbol(thisAgent, x);
419 
420  return refCount ;
421 }
422 
423 #endif /* USE_MACROS */
424 
425 /* -----------------------------------------------------------------
426  Predefined Symbols
427 
428  Certain symbols are used so frequently that we create them at
429  system startup time and never deallocate them. These symbols are
430  global variables (per-agent) and are named xxx_symbol (see glob_vars.h).
431 
432  Create_predefined_symbols() should be called to do the creation.
433  After that, the global variables can be accessed freely. Note that
434  the reference counts on these symbols should still be updated--
435  symbol_add_ref() should be called, etc.--it's just that when the
436  symbol isn't really being used, it stays around because the count
437  is still 1.
438 ----------------------------------------------------------------- */
439 
440 extern void create_predefined_symbols (agent* thisAgent);
441 extern void release_predefined_symbols (agent* thisAgent);
442 
443 #ifdef __cplusplus
444 //}
445 #endif
446 
447 #endif