00001 /* This is silently disabling the msvc header file bug with warning level 00002 4 turned on. See bugzilla bug 167 */ 00003 #ifdef _MSC_VER 00004 #pragma warning(disable : 4115) 00005 #endif 00006 00007 /************************************************************************* 00008 * 00009 * file: soarkernel.h 00010 * 00011 * ======================================================================= 00012 * 00013 * Soar 6 Include File 00014 * 00015 * This file gets #included in all Soar 6 source files. It defines all 00016 * sorts of constants and data structures, and gives prototype declarations 00017 * for various functions. 00018 * It also has insightful comments and detailed explanations and is 00019 * recommended reading for anyone who would like to know more about 00020 * the source code. 00021 * ======================================================================= 00022 * 00023 * 00024 * Copyright 1995-2003 Carnegie Mellon University, 00025 * University of Michigan, 00026 * University of Southern California/Information 00027 * Sciences Institute. All rights reserved. 00028 * 00029 * Redistribution and use in source and binary forms, with or without 00030 * modification, are permitted provided that the following conditions are met: 00031 * 00032 * 1. Redistributions of source code must retain the above copyright notice, 00033 * this list of conditions and the following disclaimer. 00034 * 2. Redistributions in binary form must reproduce the above copyright notice, 00035 * this list of conditions and the following disclaimer in the documentation 00036 * and/or other materials provided with the distribution. 00037 * 00038 * THIS SOFTWARE IS PROVIDED BY THE SOAR CONSORTIUM ``AS IS'' AND ANY EXPRESS OR 00039 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00040 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 00041 * EVENT SHALL THE SOAR CONSORTIUM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00042 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00043 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00044 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00045 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00046 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00047 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00048 * The views and conclusions contained in the software and documentation are 00049 * those of the authors and should not be interpreted as representing official 00050 * policies, either expressed or implied, of Carnegie Mellon University, the 00051 * University of Michigan, the University of Southern California/Information 00052 * Sciences Institute, or the Soar consortium. 00053 * ======================================================================= 00054 */ 00055 00056 #ifndef _SOAR_H_INCLUDED /* ExcludeFromBuildInfo */ 00057 #define _SOAR_H_INCLUDED 00058 00059 #ifndef _MSC_VER 00060 #define _GNU_SOURCE 00061 #endif 00062 00063 #if defined(MACINTOSH) /* excludeFromBuildInfo */ 00064 #include <utime.h> 00065 #include <signal.h> 00066 #include <stdlib.h> 00067 #include <time.h> 00068 00069 #elif defined(WIN32) /* excludeFromBuildInfo */ 00070 #include <stdlib.h> 00071 #include <time.h> 00072 #include <windows.h> 00073 00074 #else 00075 #include <sys/time.h> 00076 #include <stdlib.h> 00077 #endif 00078 00079 #include <string.h> 00080 #include <stdio.h> 00081 #include <stddef.h> 00082 00083 #ifdef UNIX 00084 #include <unistd.h> 00085 #endif 00086 00087 #include "soarBuildOptions.h" 00088 00089 #ifndef MAX_SIMULTANEOUS_AGENTS 00090 #define MAX_SIMULTANEOUS_AGENTS 128 00091 #endif 00092 00093 /* kjc: I don't understand what's up with all this __hpux stuff. 00094 * when I took out all the embedded old stuff about THINK_C and 00095 * __SC__, I'm left with __hpux defines and undefines that cancel 00096 * each other out. so this should be tested in HP's and this 00097 * stuff should be removed if not needed... 00098 */ 00099 /* I changed the goofy stuff to this from agent.c : */ 00100 #ifdef __hpux /* excludeFromBuildInfo */ 00101 #ifndef _INCLUDE_POSIX_SOURCE /* excludeFromBuildInfo */ 00102 #define _INCLUDE_POSIX_SOURCE 00103 #endif 00104 #define _INCLUDE_XOPEN_SOURCE /* excludeFromBuildInfo */ 00105 #define _INCLUDE_HPUX_SOURCE /* excludeFromBuildInfo */ 00106 #include <sys/types.h> 00107 #undef _INCLUDE_POSIX_SOURCE 00108 #undef _INCLUDE_XOPEN_SOURCE 00109 #undef _INCLUDE_HPUX_SOURCE 00110 #endif /* __hpux */ 00111 00112 #ifndef tolower 00113 /* I can't believe Sun's ctype.h doesn't have this. */ 00114 extern int tolower(int); 00115 #endif 00116 00117 #ifdef _MSC_VER 00118 #define snprintf _snprintf 00119 #define vsnprintf _vsnprintf 00120 #endif 00121 00122 /* this is the size of the buffers used to print out error messages, etc */ 00123 #define MESSAGE_SIZE 512 00124 /* size of the action attribute; used in rete.c, osupport.c */ 00125 #define ACTION_ATTR_SIZE 50 00126 00127 #include "sysdep.h" 00128 00129 #ifdef __cplusplus /* excludeFromBuildInfo */ 00130 #define extern extern "C" 00131 #endif 00132 00133 #define ABSTRACT_REPLAY 1 00134 00135 #define current_agent(x) (soar_agent->x) 00136 00137 #ifdef DC_HISTOGRAM 00138 00139 #define increment_current_agent_d_cycle_count { \ 00140 soar_agent->d_cycle_count++; \ 00141 if ( soar_agent->d_cycle_count > soar_agent->dc_histogram_offset && \ 00142 soar_agent->d_cycle_count % soar_agent->dc_histogram_freq == 0 && \ 00143 (soar_agent->d_cycle_count / soar_agent->dc_histogram_freq) < \ 00144 soar_agent->dc_histogram_sz ) { \ 00145 soar_agent->dc_histogram_now = TRUE; \ 00146 } \ 00147 } 00148 00149 #else 00150 00151 #define increment_current_agent_d_cycle_count { \ 00152 soar_agent->d_cycle_count++; \ 00153 } 00154 00155 #endif /* DC_HISTOGRAM */ 00156 00157 /* --------------------------- */ 00158 /* Current Soar version number */ 00159 /* --------------------------- */ 00160 00161 #define MAJOR_VERSION_NUMBER 8 00162 #define MINOR_VERSION_NUMBER 5 00163 #define MICRO_VERSION_NUMBER 0 00164 #define GREEK_VERSION_NUMBER "" 00165 00166 extern char *soar_version_string; 00167 extern char *soar_news_string; 00168 00169 /* REW: begin 05.05.97 */ 00170 #define OPERAND2_MODE_NAME "Operand2/Waterfall" 00171 /* REW: end 05.05.97 */ 00172 00173 /* --------------------------------------------------------- */ 00174 /* Line width of terminal (used for neatly formatted output) */ 00175 /* --------------------------------------------------------- */ 00176 00177 #define COLUMNS_PER_LINE 80 00178 00179 /* ------------------------------ */ 00180 /* Global type declarations, etc. */ 00181 /* ------------------------------ */ 00182 00183 typedef unsigned char byte; 00184 #ifndef HAVE_BOOL 00185 typedef char bool; 00186 #endif 00187 00188 /* Some compilers define these. */ 00189 #ifndef TRUE /* excludeFromBuildInfo */ 00190 #define TRUE (1) 00191 #endif 00192 #ifndef FALSE /* excludeFromBuildInfo */ 00193 #define FALSE (0) 00194 #endif 00195 00196 #define NIL (0) 00197 00198 #define EOF_AS_CHAR ((char)EOF) 00199 00200 #ifdef PII_TIMERS 00201 #define TIMER_VALUE unsigned long long int 00202 #else 00203 #define TIMER_VALUE struct timeval 00204 #endif 00205 00206 enum agent_id_state { 00207 UNTOUCHED, 00208 TOUCHED, 00209 ALLOCATED 00210 }; 00211 00212 /* Possible modes for numeric indifference */ 00213 enum ni_mode { 00214 NUMERIC_INDIFFERENT_MODE_AVG, 00215 NUMERIC_INDIFFERENT_MODE_SUM, 00216 }; 00217 00218 /* --------------------------------------------------------------------- 00219 Macros for Inserting and Removing Stuff from Doubly-Linked Lists 00220 00221 Note: fast_remove_from_dll() is the same as remove_from_dll() except 00222 slightly faster. I (RBD) only realized this after writing all the 00223 original code. With fast_remove_from_dll(), you have to tell it 00224 the type (i.e., structure name) of the item being spliced out of 00225 the list. At some point we might want to go through all the code 00226 and have it use fast_remove_from_dll(), but it's probably not worth 00227 the effort right now. 00228 -------------------------------------------------------------------- */ 00229 00230 #define insert_at_head_of_dll(header,item,next_field_name,prev_field_name) { \ 00231 ((item)->next_field_name) = (header) ; \ 00232 ((item)->prev_field_name) = NIL ; \ 00233 if (header) ((header)->prev_field_name) = (item) ; \ 00234 (header) = (item) ; } 00235 00236 #define remove_from_dll(header,item,next_field_name,prev_field_name) { \ 00237 if ((item)->next_field_name) \ 00238 ((item)->next_field_name->prev_field_name) = ((item)->prev_field_name); \ 00239 if ((item)->prev_field_name) { \ 00240 ((item)->prev_field_name->next_field_name) = ((item)->next_field_name); \ 00241 } else { \ 00242 (header) = ((item)->next_field_name); \ 00243 } } 00244 00245 #define fast_remove_from_dll(header,item,typename,next_field_name,prev_field_name) { \ 00246 typename *tempnext, *tempprev; \ 00247 tempnext = (item)->next_field_name; \ 00248 tempprev = (item)->prev_field_name; \ 00249 if (tempnext) tempnext->prev_field_name = tempprev; \ 00250 if (tempprev) { \ 00251 tempprev->next_field_name = tempnext; \ 00252 } else { \ 00253 (header) = tempnext; } } 00254 00255 /* ----------------- */ 00256 /* Goal Stack Levels */ 00257 /* ----------------- */ 00258 00259 typedef signed short goal_stack_level; 00260 #define TOP_GOAL_LEVEL 1 00261 #define ATTRIBUTE_IMPASSE_LEVEL 32767 00262 #define LOWEST_POSSIBLE_GOAL_LEVEL 32767 00263 00264 /* -------------------------------------------------- */ 00265 /* Names of Rete Structures */ 00266 /* (only pointers to these are used outside the rete) */ 00267 /* -------------------------------------------------- */ 00268 00269 struct token_struct; 00270 struct rete_node_struct; 00271 00272 /* REW: begin 08.20.97 */ 00273 /* The ms_change_struct is exported to the entire system 00274 (for better or worse) so 00275 this restricted definition is no longer necessary. */ 00276 /* struct ms_change_struct; */ 00277 /* REW: end 08.20.97 */ 00278 00279 struct node_varnames_struct; 00280 00281 /* -------------------------------------------------------------------- 00282 Transitive Closure Numbers 00283 00284 In many places, we do transitive closures or some similar process in 00285 which we mark identifiers and/or variables so as not to repeat them 00286 later. Marking is done by setting the "tc_num" field of the symbol 00287 to the "current transitive closure number". We don't have to go 00288 back and unmark stuff when done--we just increment the current 00289 transitive closure number next time. Whenever we need to start a 00290 new marking, we call get_new_tc_number() (see production.c comments 00291 below). 00292 -------------------------------------------------------------------- */ 00293 00294 typedef unsigned long tc_number; 00295 00296 /* ====================================================================== 00297 mem.c 00298 00299 Init_memory_utilities() should be called before any of these routines 00300 are used. 00301 00302 Basic memory allocation utilities: 00303 00304 All memory blocks are allocated via calls to allocate_memory(). It 00305 calls malloc() and aborts if we run out of memory. Free_memory() is 00306 the inverse of allocate_memory(). Allocate_memory_and_zerofill() 00307 does the obvious thing. These routines take a usage_code indicating 00308 what purpose the memory is for (hash tables, strings, etc.). This 00309 is used purely for statistics keeping. 00310 00311 the API function, soar_ecPrintMemoryStatistics(), prints out 00312 stats on the memory usage. 00313 00314 String utilities: 00315 00316 Make_memory_block_for_string() takes a pointer to a string, allocates 00317 a memory block just large enough to hold the string, and copies the 00318 string into the block. Free_memory_block_for_string() frees the 00319 block. 00320 00321 "Growable strings" provide a convenient way of building up a string 00322 piece by piece without having to pre-allocate the right amount of 00323 memory. To initialize one, say "gs = make_blank_growable_string()" 00324 where "gs" is of type "growable_string". To concatenate a new string 00325 onto the end of an existing growable string, call 00326 add_to_growable_string(&gs,new_string) [note the "&"]. When you're 00327 done using it, call free_growable_string(gs). Growable strings are 00328 implemented by allocating a block of memory large enough to hold 00329 (1) the memory block's size, (2) the current string length, and (3) 00330 the current text of the string. Add_to_growable_string() may result 00331 in a new (larger) memory block being allocated and the text of the 00332 string being copied. Three macros provide access to a growable string's 00333 parts: memsize_of_growable_string(), length_of_growable_string(), 00334 and (most importantly) text_of_growable_string(), which is of type 00335 (char *). 00336 00337 Memory pools: 00338 00339 To allocate and free memory items efficiently at run time, we use 00340 pools of small fixed-size items and do allocation and freeing using 00341 inline macros. Different memory pools are used for different things 00342 and contain different size items. Each pool consists of a memory_pool 00343 structure (used for maintaining the pool) and a chain of big blocks 00344 of memory (currently about 32K per block) obtained from allocate_memory(). 00345 We maintain a free_list of small items not being used, and allocate by 00346 grabbing the first item on the free list. If the free list is empty, 00347 we add another big block to the pool. 00348 00349 Init_memory_pool() should be called to initialize a memory_pool 00350 structure before it is used. After that, the macro forms 00351 allocate_with_pool (&mem_pool, &pointer_to_be_set_to_new_item) 00352 and free_with_pool (&mem_pool, pointer_to_item) are used to 00353 allocate and free items. The API Function, 00354 soar_ecPrintMemoryPoolStatistics(), prints stats about the 00355 various pools in use and how much memory each is using. 00356 00357 Cons cell and list utilities: 00358 00359 This provides a simple facility for manipulating generic lists, just 00360 like in Lisp. A "cons" is a pair of pointers; a "list" is just a cons 00361 (or NIL). We maintain a memory pool (see above) of conses. 00362 Allocate_cons() is like allocate_with_pool() for conses; free_cons() 00363 is like free_with_pool. Push(new_item,my_list) is a macro for adding 00364 a new item onto the front of an existing list. 00365 00366 In addition to the regular conses, we also have a pool of "dl_cons"es-- 00367 these are like conses, only doubly-linked. A "dl_list" is a just a 00368 dl_cons (or NIL). 00369 00370 Some (consed) list utility functions: destructively_reverse_list() 00371 does just what it says, and returns a pointer to the new head of the 00372 list (formerly the tail). Member_of_list() tests membership, using 00373 "==" as the equality predicates. Add_if_not_member() is like Lisp's 00374 "pushnew"; it returns the new list (possibly unchanged) list. 00375 Free_list() frees all the cons cells in the list. 00376 00377 Sometimes we need to surgically extract particular elements from a 00378 list. Extract_list_elements() and extract_dl_list_elements() do this. 00379 They use a callback function that indicates which elements to extract: 00380 the callback function is called on each element of the list, and should 00381 return TRUE for the elements to be extracted. The two extraction 00382 functions return a list (or dl_list) of the extracted elements. 00383 00384 Hash table routines: 00385 00386 We use hash tables in various places, and don't want to have to fix 00387 their size ahead of time. These routines provide hash tables that 00388 are dynamically resized as items are added and removed. We use 00389 "open hashing" with a hash table whose size is a power of two. We 00390 keep track of how many items are in the table. The table grows 00391 when # of items >= 2*size, and shrinks when # of items < size/2. 00392 To resize a hash table, we rehash every item in it. 00393 00394 Each item must be a structure whose first field is reserved for use 00395 by these hash table routines--it points to the next item in the hash 00396 bucket. Hash tables are created and initialized via make_hash_table(); 00397 you give it a hash function (i.e., a C function) that finds the hash 00398 value for a given item, hashing it to a value num_bits wide. For aid 00399 in this, we provide masks_for_n_low_order_bits[] that select out the 00400 low-order bits of a value: (x & masks_for_n_low_order_bits[23]) picks 00401 out the 23 low-order bits of x. 00402 00403 Items are added/removed from a hash table via add_to_hash_table() and 00404 remove_from_hash_table(). These calls resize the hash table if 00405 necessary. 00406 00407 The contents of a hash table (or one bucket in the table) can be 00408 retrieved via do_for_all_items_in_hash_table() and 00409 do_for_all_items_in_hash_bucket(). Each uses a callback function, 00410 invoking it with each successive item. The callback function should 00411 normally return FALSE. If the callback function ever returns TRUE, 00412 iteration over the hash table items stops and the do_for_xxx() 00413 routine returns immediately. 00414 ====================================================================== */ 00415 00416 extern void init_memory_utilities(void); 00417 00418 /* ----------------------- */ 00419 /* basic memory allocation */ 00420 /* ----------------------- */ 00421 00422 #define MISCELLANEOUS_MEM_USAGE 0 00423 #define HASH_TABLE_MEM_USAGE 1 00424 #define STRING_MEM_USAGE 2 00425 #define POOL_MEM_USAGE 3 00426 #define STATS_OVERHEAD_MEM_USAGE 4 00427 00428 #define NUM_MEM_USAGE_CODES 5 00429 00430 #ifdef DEBUG_MEMORY 00431 #define fill_with_garbage(block,size) memset((void *)(block), 0xBB, (size)) 00432 #else 00433 #define fill_with_garbage(block,size) { } 00434 #endif 00435 00436 extern void *allocate_memory(unsigned long size, int usage_code); 00437 extern void *allocate_memory_and_zerofill(unsigned long size, int usage_code); 00438 extern void free_memory(void *mem, int usage_code); 00439 00440 /* ---------------- */ 00441 /* string utilities */ 00442 /* ---------------- */ 00443 00444 #define savestring(x) (char *) strcpy ( (char *)malloc (strlen (x) + 1), (x)) /* this is relatively safe since the proper amount of memory is allocated */ 00445 00446 extern char *make_memory_block_for_string(const char *s); 00447 extern void free_memory_block_for_string(char *p); 00448 00449 typedef void *growable_string; 00450 00451 #define memsize_of_growable_string(gs) (*((int *)(gs))) 00452 #define length_of_growable_string(gs) (*(((int *)(gs))+1)) 00453 #define text_of_growable_string(gs) (((char *)(gs)) + 2*sizeof(int *)) 00454 00455 extern growable_string make_blank_growable_string(void); 00456 extern void add_to_growable_string(growable_string * gs, char *string_to_add); 00457 extern void free_growable_string(growable_string gs); 00458 00459 /* ------------ */ 00460 /* memory pools */ 00461 /* ------------ */ 00462 00463 #define MAX_POOL_NAME_LENGTH 15 00464 00465 typedef struct memory_pool_struct { 00466 void *free_list; /* header of chain of free items */ 00467 #ifdef MEMORY_POOL_STATS 00468 long used_count; /* for statistics only */ 00469 #endif 00470 #ifdef TRACK_MEMORY_USAGE 00471 long free_list_length; 00472 long pool_size; 00473 #endif 00474 00475 long item_size; /* bytes per item */ 00476 long items_per_block; /* number of items in each big block */ 00477 long num_blocks; /* number of big blocks in use by this pool */ 00478 void *first_block; /* header of chain of blocks */ 00479 char name[MAX_POOL_NAME_LENGTH]; /* name of the pool (for memory-stats) */ 00480 struct memory_pool_struct *next; /* next in list of all memory pools */ 00481 } memory_pool; 00482 00483 extern void add_block_to_memory_pool(memory_pool * p); 00484 extern void init_memory_pool(memory_pool * p, long item_size, char *name); 00485 00486 #ifdef MEMORY_POOL_STATS 00487 #define increment_used_count(p) {(p)->used_count++;} 00488 #define decrement_used_count(p) {(p)->used_count--;} 00489 #else 00490 #define increment_used_count(p) { } 00491 #define decrement_used_count(p) { } 00492 #endif 00493 00494 #ifdef TRACK_MEMORY_USAGE 00495 #define decrement_free_list_length(p) {(p)->free_list_length--;} 00496 #define increment_free_list_length(p) {(p)->free_list_length++;} 00497 #else 00498 #define decrement_free_list_length(p) { } 00499 #define increment_free_list_length(p) { } 00500 #endif 00501 00502 #ifdef USE_DEBUG_UTILS 00503 00504 #define allocate_with_pool(p,dest_item_pointer) allocate_with_pool_fn( (p), (void *) (dest_item_pointer) ) 00505 00506 #define free_with_pool(p,item) free_with_pool_fn( (p), (item) ) 00507 00508 extern void allocate_with_pool_fn(memory_pool * p, void **dest); 00509 extern void free_with_pool_fn(memory_pool * p, void *item); 00510 00511 #else 00512 00513 #define allocate_with_pool(p,dest_item_pointer) { \ 00514 if (! (p)->free_list) add_block_to_memory_pool(p); \ 00515 (*(dest_item_pointer)) = (p)->free_list; \ 00516 (p)->free_list = *(void * *)(*(dest_item_pointer)); \ 00517 fill_with_garbage (*(dest_item_pointer), (p)->item_size); \ 00518 increment_used_count(p); \ 00519 decrement_free_list_length(p); } 00520 00521 #define free_with_pool(p,item) { \ 00522 fill_with_garbage ((item), (p)->item_size); \ 00523 *(void * *)(item) = (p)->free_list; \ 00524 (p)->free_list = (void *)(item); \ 00525 decrement_used_count(p); \ 00526 increment_free_list_length(p); } 00527 00528 #endif 00529 00530 /* ------------------------- */ 00531 /* Cons cell, list utilities */ 00532 /* ------------------------- */ 00533 00534 typedef struct cons_struct { 00535 void *first; 00536 struct cons_struct *rest; 00537 } cons; 00538 00539 typedef cons list; 00540 00541 typedef struct dl_cons_struct { 00542 void *item; 00543 struct dl_cons_struct *next; 00544 struct dl_cons_struct *prev; 00545 } dl_cons; 00546 00547 typedef dl_cons dl_list; 00548 00549 #define allocate_cons(dest_cons_pointer) \ 00550 allocate_with_pool (¤t_agent(cons_cell_pool), (void **)(dest_cons_pointer)) 00551 #define free_cons(c) free_with_pool (¤t_agent(cons_cell_pool), (c)) 00552 00553 #define push(item,list_header) { \ 00554 cons *push_cons_xy298; \ 00555 allocate_cons ((void **)&push_cons_xy298); \ 00556 push_cons_xy298->first = (item); \ 00557 push_cons_xy298->rest = (list_header); \ 00558 (list_header) = push_cons_xy298; } 00559 00560 extern list *destructively_reverse_list(list * c); 00561 extern bool member_of_list(void *item, list * the_list); 00562 extern list *add_if_not_member(void *item, list * old_list); 00563 extern void free_list(list * the_list); 00564 00565 typedef bool(*cons_test_fn) (cons * c); 00566 typedef bool(*dl_cons_test_fn) (dl_cons * dc); 00567 00568 extern list *extract_list_elements(list ** header, cons_test_fn f); 00569 extern dl_list *extract_dl_list_elements(dl_list ** header, dl_cons_test_fn f); 00570 00571 /* ----------------------------- */ 00572 /* Resizable hash table routines */ 00573 /* ----------------------------- */ 00574 00575 extern unsigned long masks_for_n_low_order_bits[33]; 00576 typedef unsigned long ((*hash_function) (void *item, short num_bits)); 00577 00578 typedef struct item_in_hash_table_struct { 00579 struct item_in_hash_table_struct *next; 00580 char data; 00581 } item_in_hash_table; 00582 00583 typedef item_in_hash_table *bucket_array; 00584 00585 typedef struct hash_table_struct { 00586 unsigned long count; /* number of items in the table */ 00587 unsigned long size; /* number of buckets */ 00588 short log2size; /* log (base 2) of size */ 00589 short minimum_log2size; /* table never shrinks below this size */ 00590 bucket_array *buckets; 00591 hash_function h; /* call this to hash or rehash an item */ 00592 } hash_table; 00593 00594 extern struct hash_table_struct *make_hash_table(short minimum_log2size, hash_function h); 00595 extern void remove_from_hash_table(struct hash_table_struct *ht, void *item); 00596 extern void add_to_hash_table(struct hash_table_struct *ht, void *item); 00597 00598 typedef bool(*hash_table_callback_fn) (void *item); 00599 00600 extern void do_for_all_items_in_hash_table(struct hash_table_struct *ht, hash_table_callback_fn f); 00601 extern void do_for_all_items_in_hash_bucket(struct hash_table_struct *ht, 00602 hash_table_callback_fn f, unsigned long hash_value); 00603 00604 /* ====================================================================== 00605 lexer.c 00606 00607 The lexer reads files and returns a stream of lexemes. Get_lexeme() is 00608 the main routine; it looks for the next lexeme in the input, and stores 00609 it in the global variable "lexeme". See the structure definition below. 00610 00611 Restrictions: the lexer cannot read individual input lines longer than 00612 MAX_LEXER_LINE_LENGTH characters. Thus, a single lexeme can't be longer 00613 than that either. 00614 00615 The lexer maintains a stack of files being read, in order to handle nested 00616 loads. Start_lex_from_file() and stop_lex_from_file() push and pop the 00617 stack. Immediately after start_lex_from_file(), the current lexeme (global 00618 variable) is undefined. Immediately after stop_lex_from_file(), the 00619 current lexeme is automatically restored to whatever it was just before 00620 the corresponding start_lex_from_file() call. 00621 00622 Determine_possible_symbol_types_for_string() is a utility routine which 00623 figures out what kind(s) of symbol a given string could represent. 00624 00625 Print_location_of_most_recent_lexeme() is used to print an indication 00626 of where a parser error occurred. It tries to print out the current 00627 source line with a pointer to where the error was detected. 00628 00629 Current_lexer_parentheses_level() returns the current level of parentheses 00630 nesting (0 means no open paren's have been encountered). 00631 Skip_ahead_to_balanced_parentheses() eats lexemes until the appropriate 00632 closing paren is found (0 means eat until back at the top level). 00633 00634 Fake_rparen_at_next_end_of_line() tells the lexer to insert a fake 00635 R_PAREN_LEXEME token the next time it reaches the end of a line. 00636 00637 Set_lexer_allow_ids() tells the lexer whether to allow identifiers to 00638 be read. If FALSE, things that look like identifiers will be returned 00639 as SYM_CONSTANT_LEXEME's instead. 00640 ====================================================================== */ 00641 00642 #define reading_from_top_level() (! current_agent(current_file)->parent_file) 00643 00644 #define MAX_LEXER_LINE_LENGTH 1000 00645 #define MAX_LEXEME_LENGTH (MAX_LEXER_LINE_LENGTH+5) /* a little bigger to avoid 00646 any off-by-one-errors */ 00647 00648 enum lexer_token_type { 00649 EOF_LEXEME, /* end-of-file */ 00650 IDENTIFIER_LEXEME, /* identifier */ 00651 VARIABLE_LEXEME, /* variable */ 00652 SYM_CONSTANT_LEXEME, /* symbolic constant */ 00653 INT_CONSTANT_LEXEME, /* integer constant */ 00654 FLOAT_CONSTANT_LEXEME, /* floating point constant */ 00655 L_PAREN_LEXEME, /* "(" */ 00656 R_PAREN_LEXEME, /* ")" */ 00657 L_BRACE_LEXEME, /* "{" */ 00658 R_BRACE_LEXEME, /* "}" */ 00659 PLUS_LEXEME, /* "+" */ 00660 MINUS_LEXEME, /* "-" */ 00661 RIGHT_ARROW_LEXEME, /* "-->" */ 00662 GREATER_LEXEME, /* ">" */ 00663 LESS_LEXEME, /* "<" */ 00664 EQUAL_LEXEME, /* "=" */ 00665 LESS_EQUAL_LEXEME, /* "<=" */ 00666 GREATER_EQUAL_LEXEME, /* ">=" */ 00667 NOT_EQUAL_LEXEME, /* "<>" */ 00668 LESS_EQUAL_GREATER_LEXEME, /* "<=>" */ 00669 LESS_LESS_LEXEME, /* "<<" */ 00670 GREATER_GREATER_LEXEME, /* ">>" */ 00671 AMPERSAND_LEXEME, /* "&" */ 00672 AT_LEXEME, /* "@" */ 00673 TILDE_LEXEME, /* "~" */ 00674 UP_ARROW_LEXEME, /* "^" */ 00675 EXCLAMATION_POINT_LEXEME, /* "!" */ 00676 COMMA_LEXEME, /* "," */ 00677 PERIOD_LEXEME, /* "." */ 00678 QUOTED_STRING_LEXEME, /* string in double quotes */ 00679 DOLLAR_STRING_LEXEME 00680 }; /* string for shell escape */ 00681 00682 #define LENGTH_OF_LONGEST_SPECIAL_LEXEME 3 /* length of "-->" and "<=>"-- 00683 if a longer one is added, be 00684 sure to update this! */ 00685 00686 struct lexeme_info { 00687 enum lexer_token_type type; /* what kind of lexeme it is */ 00688 char string[MAX_LEXEME_LENGTH + 1]; /* text of the lexeme */ 00689 int length; /* length of the above string */ 00690 long int_val; /* for INT_CONSTANT_LEXEME's */ 00691 float float_val; /* for FLOAT_CONSTANT_LEXEME's */ 00692 char id_letter; /* for IDENTIFIER_LEXEME's */ 00693 unsigned long id_number; /* for IDENTIFIER_LEXEME's */ 00694 }; 00695 00696 extern void determine_possible_symbol_types_for_string(char *s, 00697 int length_of_s, 00698 bool * possible_id, 00699 bool * possible_var, 00700 bool * possible_sc, 00701 bool * possible_ic, bool * possible_fc, bool * rereadable); 00702 00703 extern void init_lexer(void); 00704 extern void start_lex_from_file(char *filename, FILE * already_opened_file); 00705 extern void stop_lex_from_file(void); 00706 00707 extern void get_lexeme(void); 00708 extern void print_location_of_most_recent_lexeme(void); 00709 00710 extern int current_lexer_parentheses_level(void); 00711 extern void skip_ahead_to_balanced_parentheses(int parentheses_level); 00712 extern void fake_rparen_at_next_end_of_line(void); 00713 extern void set_lexer_allow_ids(bool allow_identifiers); 00714 00715 extern void determine_type_of_constituent_string(void); 00716 00717 /* (RBD) the rest of this stuff shouldn't be in the module interface... */ 00718 00719 #define BUFSIZE (MAX_LEXER_LINE_LENGTH+2) /* +2 for newline and null at end */ 00720 00721 /* --- we'll use one of these structures for each file being read --- */ 00722 00723 typedef struct lexer_source_file_struct { 00724 struct lexer_source_file_struct *parent_file; 00725 char *filename; 00726 FILE *file; 00727 bool fake_rparen_at_eol; 00728 bool allow_ids; 00729 int parentheses_level; /* 0 means top level, no left paren's seen */ 00730 int current_column; /* column number of next char to read (0-based) */ 00731 unsigned long current_line; /* line number of line in buffer (1-based) */ 00732 int column_of_start_of_last_lexeme; /* (used for error messages) */ 00733 unsigned long line_of_start_of_last_lexeme; 00734 char buffer[BUFSIZE]; /* holds text of current input line */ 00735 struct lexeme_info saved_lexeme; /* save/restore it during nested loads */ 00736 char saved_current_char; /* save/restore this too */ 00737 } lexer_source_file; 00738 00739 /* ======================================================================= 00740 symtab.c 00741 00742 Soar 6 uses five kinds of symbols: symbolic constants, integer 00743 constants, floating-point constants, identifiers, and variables. 00744 We use five resizable hash tables, one for each kind of symbol. 00745 00746 "symbol" is typedef-ed as a union of the five kinds of symbol 00747 structures. Some fields common to all symbols are accessed via 00748 sym->common.field_name; fields particular to a certain kind of 00749 symbol are accessed via sym->var.field_name_on_variables, etc. 00750 (See the definitions below.) Note that "common" is #defined below. 00751 00752 Some (but not all) of the fields common to all symbols are: 00753 symbol_type: indicates which of the five kinds of symbols this is 00754 reference_count: current reference count for this symbol 00755 hash_id: used for hash functions in the rete (and elsewhere) 00756 00757 Fields on symbolic constants: 00758 name: points to null-terminated string giving its name 00759 production: points to a production structure, or NIL if there is 00760 no production with that name 00761 00762 Fields on integer constants: 00763 value: gives the value of the symbol. This is of type (long). 00764 00765 Fields on floating-point constants: 00766 value: gives the value of the symbol. This is of type (float). 00767 00768 Fields on variables: 00769 name: points to null-terminated string giving its name 00770 tc_num: used for transitive closure computations 00771 current_binding_value: when productions are fired, this indicates 00772 the variable's binding 00773 gensym_number: used by the variable generator to prevent certain 00774 already-in-use variables from being generated 00775 rete_binding_locations: used temporarily by the Rete, while adding 00776 productions, to store a list of places where this 00777 variable is bound and/or tested 00778 00779 Fields on identifiers: 00780 00781 name_number, name_letter: indicate the name of the identifier 00782 00783 isa_goal, isa_impasse: indicate whether this is the identifier of a 00784 goal or attribute impasse 00785 00786 isa_operator: keeps a count of how many (normal or acceptable 00787 preference) wmes contain (^operator <this-id>). 00788 The tracing code uses this to figure out whether 00789 a given object is an operator. 00790 00791 allow_bottom_up_chunks: Used for bottom-up chunking, and only on goal 00792 identifiers. This is TRUE iff no chunk has yet been built for a 00793 subgoal of this goal. 00794 00795 could_be_a_link_from_below: TRUE if there might be a link to this id 00796 from some other id lower in the goal stack. 00797 00798 did_PE: 00799 00800 level: current goal_stack_level of this id 00801 00802 promotion_level: level to which this id is going to be promoted as 00803 soon as ownership info is updated. 00804 00805 link_count: count of how many links there are to this id. 00806 00807 unknown_level: if the goal_stack_level of this id is known, this is 00808 NIL. If the level isn't known, it points to a dl_cons in a dl_list 00809 used by the demotion routines. 00810 00811 slots: this is the header for a dll of the slots for this id. 00812 00813 tc_num: used for transitive closures, marking id's, etc. 00814 00815 variablization: used by the chunker when variablizing chunks--this 00816 points to the variable to which this id gets changed 00817 00818 impasse_wmes: for goal and impasse ids only: this is the header 00819 of the dll of architecture-created wmes (e.g., (G37 ^object G36)) 00820 00821 higher_goal, lower_goal: for goals, these point to adjacent goals 00822 in the context stack 00823 problem_space_slot, state_slot, operator_slot: for goals, these 00824 point to the corresponding context slots 00825 preferences_from_goal: for goals, this is the header of the dll 00826 of all preferences supported by this goal. This is needed so 00827 we can remove o-supported preferences when the goal goes away. 00828 00829 gds: pointer to a goal's dependency set 00830 saved_firing_type: the firing type that must be restored if 00831 Waterfall processing returns to this level. see consistency.c 00832 ms_o_assertions: dll of o-assertions at this level 00833 ms_i_assertions: dll of i-assertions at this level 00834 ms_retractions: dll of all retractions at this level 00835 00836 associated_output_links: used by the output module 00837 00838 input_wmes: dll of wmes added by input functions 00839 00840 Reference counting for symbols: I can't remember all the places I add 00841 reference counts to symbols. Here's a bunch I can remember though. 00842 If you're not sure whether to add/remove a reference for something, 00843 it's better to play it safe and do the add/remove. 00844 00845 +1 for each occurrence in a rete test or alpha mem constant test 00846 +1 for each occurrence in a condition test anywhere 00847 +1 for each occurrence in a Not 00848 +1 for each occurrence in a saved_test 00849 +1 for each occurrence in a WME 00850 +1 for each occurrence in a preference 00851 +1 for each occurrence as {id or attr} of a slot 00852 +1 for goal/impasse identifiers 00853 +1 if it's the name of a production 00854 +1 if it's a predefined symbol (e.g., "goal" or "operator") 00855 +1 for each enqueued add-link or remove-link to/from it 00856 +1 for each occurrence in a global var. (e.g., chunk-free-problem-spaces) 00857 00858 We deallocate a symbol when its reference count goes to 0. 00859 ======================================================================= */ 00860 00861 #define VARIABLE_SYMBOL_TYPE 0 00862 #define IDENTIFIER_SYMBOL_TYPE 1 00863 #define SYM_CONSTANT_SYMBOL_TYPE 2 00864 #define INT_CONSTANT_SYMBOL_TYPE 3 00865 #define FLOAT_CONSTANT_SYMBOL_TYPE 4 00866 00867 /* WARNING: In the following structure, next_in_hash_table MUST be the 00868 first field. This field is used by the resizable hash table routines. */ 00869 00870 typedef struct symbol_common_data_struct { 00871 union symbol_union *next_in_hash_table; /* next item in hash bucket */ 00872 unsigned long reference_count; 00873 byte symbol_type; /* one of the above xxx_SYMBOL_TYPE's */ 00874 byte decider_flag; /* used only by the decider */ 00875 union a_union { 00876 struct wme_struct *decider_wme; /* used only by the decider */ 00877 unsigned long retesave_symindex; /* used for rete fastsave/fastload */ 00878 } a; 00879 unsigned long hash_id; /* used for hashing in the rete */ 00880 } symbol_common_data; 00881 00882 /* WARNING: In the following structures (the five kinds of symbols), 00883 common_symbol_info MUST be the first field. */ 00884 00885 typedef struct sym_constant_struct { 00886 symbol_common_data common_symbol_info; 00887 char *name; 00888 struct production_struct *production; /* NIL if no prod. has this name */ 00889 } sym_constant; 00890 00891 typedef struct int_constant_struct { 00892 symbol_common_data common_symbol_info; 00893 long value; 00894 } int_constant; 00895 00896 typedef struct float_constant_struct { 00897 symbol_common_data common_symbol_info; 00898 float value; 00899 } float_constant; 00900 00901 typedef struct variable_struct { 00902 symbol_common_data common_symbol_info; 00903 char *name; 00904 tc_number tc_num; 00905 union symbol_union *current_binding_value; 00906 unsigned long gensym_number; 00907 list *rete_binding_locations; 00908 } variable; 00909 00910 /* Note: I arranged the fields below to try to minimize space */ 00911 typedef struct identifier_struct { 00912 symbol_common_data common_symbol_info; 00913 unsigned long name_number; 00914 char name_letter; 00915 00916 bool isa_goal; /* TRUE iff this is a goal identifier */ 00917 bool isa_impasse; /* TRUE iff this is an attr. impasse identifier */ 00918 00919 bool did_PE; /* RCHONG: 10.11 */ 00920 00921 unsigned short isa_operator; 00922 00923 bool allow_bottom_up_chunks; 00924 00925 /* --- ownership, promotion, demotion, & garbage collection stuff --- */ 00926 bool could_be_a_link_from_below; 00927 goal_stack_level level; 00928 goal_stack_level promotion_level; 00929 unsigned long link_count; 00930 dl_cons *unknown_level; 00931 00932 struct slot_struct *slots; /* dll of slots for this identifier */ 00933 tc_number tc_num; /* used for transitive closures, marking, etc. */ 00934 union symbol_union *variablization; /* used by the chunker */ 00935 00936 /* --- fields used only on goals and impasse identifiers --- */ 00937 struct wme_struct *impasse_wmes; 00938 00939 /* --- fields used only on goals --- */ 00940 union symbol_union *higher_goal, *lower_goal; 00941 struct slot_struct *operator_slot; 00942 struct preference_struct *preferences_from_goal; 00943 00944 /* REW: begin 09.15.96 */ 00945 struct gds_struct *gds; /* Pointer to a goal's dependency set */ 00946 /* REW: begin 09.15.96 */ 00947 00948 /* REW: begin 08.20.97 */ 00949 int saved_firing_type; /* FIRING_TYPE that must be restored if Waterfall 00950 processing returns to this level. 00951 See consistency.c */ 00952 struct ms_change_struct *ms_o_assertions; /* dll of o assertions at this level */ 00953 struct ms_change_struct *ms_i_assertions; /* dll of i assertions at this level */ 00954 struct ms_change_struct *ms_retractions; /* dll of retractions at this level */ 00955 /* REW: end 08.2097 */ 00956 00957 /* --- fields used for Soar I/O stuff --- */ 00958 list *associated_output_links; 00959 struct wme_struct *input_wmes; 00960 } identifier; 00961 00962 typedef union symbol_union { 00963 variable var; 00964 identifier id; 00965 sym_constant sc; 00966 int_constant ic; 00967 float_constant fc; 00968 } Symbol; 00969 00970 /* WARNING: this #define's "common". Don't use "common" anywhere in the 00971 code unless you intend this meaning of it. This is so we can 00972 conveniently access fields used in all kinds of symbols, like this: 00973 "sym.common.reference_count" rather than "sym.var.common.reference_count" 00974 or "sym.id.common.reference_count", etc. */ 00975 00976 #define common var.common_symbol_info 00977 00978 /* ----------------------------------------------------------------- 00979 Symbol Table Routines 00980 00981 Initialization: 00982 00983 Init_symbol_tables() should be called first, to initialize the 00984 module. 00985 00986 Lookup and Creation: 00987 00988 The find_xxx() routines look for an existing symbol and return it 00989 if found; if no such symbol exists, they return NIL. 00990 00991 The make_xxx() routines look for an existing symbol; if the find one, 00992 they increment the reference count and return it. If no such symbol 00993 exists, they create a new one, set the reference count to 1, and 00994 return it. 00995 00996 Note that rather than a make_identifier() routine, we have a 00997 make_new_identifier() routine, which takes two arguments: the first 00998 letter for the new identifier, and its initial goal_stack_level. 00999 There is no way to force creation of an identifier with a particular 01000 name letter/number combination like J37. 01001 01002 Reference Counting: 01003 01004 Symbol_add_ref() and symbol_remove_ref() are macros for incrementing 01005 and decrementing the reference count on a symbol. When the count 01006 goes to zero, symbol_remove_ref() calls deallocate_symbol(). 01007 01008 Other Utilities: 01009 01010 Reset_id_counters() is called during an init-soar to reset the id 01011 gensym numbers to 1. It first makes sure there are no existing 01012 identifiers in the system--otherwise we might generate a second 01013 identifier with the same name later on. 01014 01015 Reset_id_and_variable_tc_numbers() resets the tc_num field of every 01016 existing id and variable to 0. 01017 01018 Reset_variable_gensym_numbers() resets the gensym_number field of 01019 every existing variable to 0. 01020 01021 Print_internal_symbols() just prints a list of all existing symbols. 01022 (This is useful for debugging memory leaks.) 01023 01024 Generate_new_sym_constant() is used to gensym new symbols that are 01025 guaranteed to not already exist. It takes two arguments: "prefix" 01026 (the desired prefix of the new symbol's name), and "counter" (a 01027 pointer to a counter (unsigned long) that is incremented to produce 01028 new gensym names). 01029 ----------------------------------------------------------------- */ 01030 01031 extern void init_symbol_tables(void); 01032 01033 extern Symbol *find_variable(char *name); 01034 extern Symbol *find_identifier(char name_letter, unsigned long name_number); 01035 extern Symbol *find_sym_constant(const char *name); /* AGR 600 */ 01036 extern Symbol *find_int_constant(long value); 01037 extern Symbol *find_float_constant(float value); 01038 01039 extern Symbol *make_variable(char *name); 01040 extern Symbol *make_sym_constant(const char *name); 01041 extern Symbol *make_int_constant(long value); 01042 extern Symbol *make_float_constant(float value); 01043 extern Symbol *make_new_identifier(char name_letter, goal_stack_level level); 01044 01045 /* --- macros used for changing the reference count --- */ 01046 #define symbol_add_ref(x) {(x)->common.reference_count++;} 01047 #define symbol_remove_ref(x) { \ 01048 (x)->common.reference_count--; \ 01049 if ((x)->common.reference_count == 0) \ 01050 deallocate_symbol(x); \ 01051 } 01052 01053 extern void deallocate_symbol(Symbol * sym); 01054 01055 extern void reset_id_counters(void); 01056 extern void reset_id_and_variable_tc_numbers(void); 01057 extern void reset_variable_gensym_numbers(void); 01058 extern bool print_sym(void *item); 01059 01060 extern Symbol *generate_new_sym_constant(char *prefix, unsigned long *counter); 01061 01062 /* ----------------------------------------------------------------- 01063 Predefined Symbols 01064 01065 Certain symbols are used so frequently that we create them at 01066 system startup time and never deallocate them. These symbols are 01067 global variables (per-agent) and are named xxx_symbol (see glob_vars.h). 01068 01069 Create_predefined_symbols() should be called to do the creation. 01070 After that, the global variables can be accessed freely. Note that 01071 the reference counts on these symbols should still be updated-- 01072 symbol_add_ref() should be called, etc.--it's just that when the 01073 symbol isn't really being used, it stays around because the count 01074 is still 1. 01075 ----------------------------------------------------------------- */ 01076 01077 extern void create_predefined_symbols(void); 01078 01079 /* ========================================================================= */ 01080 /* */ 01081 /* Global Data Structures */ 01082 /* */ 01083 /* ========================================================================= */ 01084 01085 /* ------------------------------------------------------------------------ 01086 Working Memory Elements (WMEs) 01087 01088 Fields in a WME: 01089 01090 id, attr, value: points to symbols for the wme fields 01091 01092 acceptable: TRUE iff this is an acceptable pref. wme 01093 01094 timetag: timetag of the wme 01095 01096 reference count: (see below) 01097 01098 rete_next, rete_prev: pointers in the doubly-linked list of all 01099 wmes currently known to the rete (header is all_wmes_in_rete) 01100 (this equals WM except while WM is being changed) 01101 01102 right_mems: header of a doubly-linked list of right memory entries 01103 (in one or more alpha memories containing the wme). This is used 01104 only by the Rete, as part of list-based remove. 01105 01106 tokens: header of a doubly-linked list of tokens in the Rete. 01107 This is used only by the Rete, as part of list-based remove. 01108 01109 next, prev: pointers in a doubly-linked list of wmes. 01110 Depending on the wme type, the header of this DLL is: 01111 - slot.wmes (for ordinary wmes) 01112 - slot.acceptable_preference_wmes (for acceptable pref. wmes) 01113 - id.impasse_wmes (for architecture-created goal/impasse wmes) 01114 - id.input_wmes (for Soar I/O wmes) 01115 01116 preference: points to the preference supporting the wme. For I/O 01117 wmes and (most) architecture-created wmes, this is NIL. 01118 01119 output_link: this is used only for top-state output links. 01120 It points to an output_link structure used by the I/O routines. 01121 01122 grounds_tc, potentials_tc, locals_tc: used by the chunker to indicate 01123 whether this wme is in the grounds, potentials, and/or locals sets 01124 01125 chunker_bt_pref: used by the chunker; set to cond->bt.trace when 01126 a wme is added to either the potentials or locals set 01127 01128 These are the additions to the WME structure that will be used 01129 to track dependencies for goals. Each working memory element 01130 now includes a pointer to a gds_struct (defined below) and 01131 pointers to other WMEs on the same GDS. 01132 01133 gds: the goal dependency set the wme is in 01134 gds_next, gds_prev: used for dll of all wmes in gds 01135 01136 If a particular working memory element is not dependent for any goal, 01137 then the values for these pointers will all be NIL. If a WME is 01138 dependent for more than one goal, then it will point to the GDS 01139 of the highest goal. 01140 01141 01142 01143 01144 Reference counts on wmes: 01145 +1 if the wme is currently in WM 01146 +1 for each instantiation condition that points to it (bt.wme) 01147 We deallocate a wme when its reference count goes to 0. 01148 ------------------------------------------------------------------------ */ 01149 01150 typedef struct wme_struct { 01151 /* WARNING: The next three fields (id,attr,value) MUST be consecutive-- 01152 the rete code relies on this! */ 01153 Symbol *id; 01154 Symbol *attr; 01155 Symbol *value; 01156 bool acceptable; 01157 unsigned long timetag; 01158 unsigned long reference_count; 01159 struct wme_struct *rete_next, *rete_prev; /* used for dll of wmes in rete */ 01160 struct right_mem_struct *right_mems; /* used for dll of rm's it's in */ 01161 struct token_struct *tokens; /* dll of tokens in rete */ 01162 struct wme_struct *next, *prev; /* (see above) */ 01163 struct preference_struct *preference; /* pref. supporting it, or NIL */ 01164 struct output_link_struct *output_link; /* for top-state output commands */ 01165 tc_number grounds_tc; /* for chunker use only */ 01166 tc_number potentials_tc, locals_tc; 01167 struct preference_struct *chunker_bt_pref; 01168 01169 /* REW: begin 09.15.96 */ 01170 struct gds_struct *gds; 01171 struct wme_struct *gds_next, *gds_prev; /* used for dll of wmes in gds */ 01172 /* REW: end 09.15.96 */ 01173 01174 } wme; 01175 01176 /* REW: begin 09.15.96 */ 01177 01178 /* ------------------------------------------------------------------------ 01179 Goal Dependency Set 01180 01181 The Goal Dependency Set is a data strcuture used in Operand2 to maintain 01182 the integrity of a subgoal with respect to changes in supergoal WMEs. 01183 Whenever a WME in the goal's dependency set changes, the goal is immediately 01184 removed. The routines for maintaining the GDS and determining if a goal 01185 should be retracted are in decide.c 01186 01187 Fields in a goal dependency set: 01188 01189 goal: points to the goal for which this dependency set was created. 01190 The goal also has a pointer back to the GDS. 01191 01192 wmes_in_gds: A DLL of WMEs in the goal dependency set 01193 01194 The GDS is created only when necessary; that is, when an o-suppported WME 01195 is created in some subgoal and that subgoal has no GDS already. The 01196 instantiations that led to the creation of the o-supported WME are 01197 examined; any supergoal WMEs in these instantiations are added to the 01198 wmes_in_gds DLL. The GDS for each goal is examined for every WM change; 01199 if a WME changes that is on a GDS, the goal that the GDS points to is 01200 immediately removed. 01201 01202 When a goal is removed, the GDS is not immediately removed. Instead, 01203 whenever a WME is removed (or when it is added to another GDS), we check 01204 to also make certain that its GDS has other WMEs on the wmes_in_gds DLL. 01205 If not, then we remove the GDS then. This delay avoids having to scan 01206 over all the WMEs in the GDS in addition to removing the goal (i.e., the 01207 maintenance cost is amortized over a number of WM phases). 01208 01209 */ 01210 01211 typedef struct gds_struct { 01212 Symbol *goal; /* pointer to the goal for the dependency set */ 01213 wme *wmes_in_gds; /* pointer to the dll of WMEs in GDS of goal */ 01214 } goal_dependency_set; 01215 /* REW: end 09.15.96 */ 01216 01217 /* ------------------------------------------------------------------------ 01218 Preferences 01219 01220 Fields in a preference: 01221 01222 type: indicates the type of the preference. This is one of the 01223 types defined below: ACCEPTABLE_PREFERENCE_TYPE, etc. 01224 01225 o_supported: TRUE iff the preference has o-support 01226 01227 in_tm: TRUE iff the preference is currently in temporary memory 01228 01229 on_goal_list: TRUE iff the preference is on the list of preferences 01230 supported by its match goal (see all_of_goal_next below) 01231 01232 reference_count: (see below) 01233 01234 id, attr, value, referent: points to the symbols. Referent is only 01235 used for binary preferences. 01236 01237 slot: points to the slot this preference is for. (NIL if the 01238 preference is not in TM.) 01239 01240 next, prev: used for a doubly-linked list of preferences of the 01241 same type in that particular slot 01242 01243 all_of_slot_next, all_of_slot_prev: used for a doubly-linked list 01244 of all preferences (of any type) in that particular slot 01245 01246 all_of_goal_next, all_of_goal_prev: used for a doubly-linked list 01247 of all preferences supported by this particular match goal. 01248 This is needed in order to remove all o-support from a particular 01249 goal when that goal is removed from the context stack. 01250 01251 next_clone, prev_clone: used for a doubly-linked list of all "clones" 01252 of this preference. When a result is returned from a subgoal and a 01253 chunk is built, we get two copies of the "same" preference, one from 01254 the subgoal's production firing, and one from the chunk instantiation. 01255 If results are returned more than one level, or the same result is 01256 returned simultaneously by multiple production firings, we can get 01257 lots of copies of the "same" preference. These clone preferences 01258 are kept on a list so that we can find the right one to backtrace 01259 through, given a wme supported by "all the clones." 01260 01261 inst: points to the instantiation that generated this preference 01262 01263 inst_next, inst_prev: used for a doubly-linked list of all 01264 existing preferences that were generated by that instantiation 01265 01266 next_candidate: used by the decider for lists of candidate values 01267 for a certain slot 01268 01269 next_result: used by the chunker for a list of result preferences 01270 01271 Reference counts on preferences: 01272 +1 if the preference is currently in TM 01273 +1 for each instantiation condition that points to it (bt.trace) 01274 +1 if it supports an installed context WME 01275 01276 We deallocate a preference if: 01277 (1) reference_count==0 and all its clones have reference_count==0 01278 (hence it couldn't possibly be needed anymore) 01279 or (2) its match goal is removed from the context stack 01280 (hence there's no way we'll ever want to BT through it) 01281 ------------------------------------------------------------------------ */ 01282 01283 /* WARNING: preference types must be numbered 0..(NUM_PREFERENCE_TYPES-1), 01284 because the slot structure contains an array using these indices. */ 01285 #define NUM_PREFERENCE_TYPES 13 /* number of different preference types */ 01286 01287 #define ACCEPTABLE_PREFERENCE_TYPE 0 01288 #define REQUIRE_PREFERENCE_TYPE 1 01289 #define REJECT_PREFERENCE_TYPE 2 01290 #define PROHIBIT_PREFERENCE_TYPE 3 01291 #define RECONSIDER_PREFERENCE_TYPE 4 01292 #define UNARY_INDIFFERENT_PREFERENCE_TYPE 5 01293 #define UNARY_PARALLEL_PREFERENCE_TYPE 6 01294 #define BEST_PREFERENCE_TYPE 7 01295 #define WORST_PREFERENCE_TYPE 8 01296 #define BINARY_INDIFFERENT_PREFERENCE_TYPE 9 01297 #define BINARY_PARALLEL_PREFERENCE_TYPE 10 01298 #define BETTER_PREFERENCE_TYPE 11 01299 #define WORSE_PREFERENCE_TYPE 12 01300 #define preference_is_unary(p) ((p)<9) 01301 #define preference_is_binary(p) ((p)>8) 01302 01303 extern char *preference_name[NUM_PREFERENCE_TYPES]; 01304 01305 typedef struct preference_struct { 01306 byte type; /* acceptable, better, etc. */ 01307 bool o_supported; /* is the preference o-supported? */ 01308 bool in_tm; /* is this currently in TM? */ 01309 bool on_goal_list; /* is this pref on the list for its match goal */ 01310 unsigned long reference_count; 01311 Symbol *id; 01312 Symbol *attr; 01313 Symbol *value; 01314 Symbol *referent; 01315 struct slot_struct *slot; 01316 01317 /* dll of pref's of same type in same slot */ 01318 struct preference_struct *next, *prev; 01319 01320 /* dll of all pref's in same slot */ 01321 struct preference_struct *all_of_slot_next, *all_of_slot_prev; 01322 01323 /* dll of all pref's from the same match goal */ 01324 struct preference_struct *all_of_goal_next, *all_of_goal_prev; 01325 01326 /* dll (without header) of cloned preferences (created when chunking) */ 01327 struct preference_struct *next_clone, *prev_clone; 01328 01329 struct instantiation_struct *inst; 01330 struct preference_struct *inst_next, *inst_prev; 01331 struct preference_struct *next_candidate; 01332 struct preference_struct *next_result; 01333 01334 #ifdef NO_TOP_JUST 01335 01336 Symbol *match_goal; /* Symbol, or NIL if none */ 01337 goal_stack_level match_goal_level; /* level, or ATTRIBUTE_IMPASSE_LEVEL */ 01338 #endif 01339 01340 #ifdef NUMERIC_INDIFFERENCE 01341 /* REW: 2003-01-08 Behavior Variability Kernel Experiements 01342 See decide.c for more information 01343 This is just a hack until we determine 01344 what we really want from these changes. 01345 */ 01346 01347 int total_preferences_for_candidate; 01348 double sum_of_probability; 01349 01350 /* END: REW: 2003-01-08 */ 01351 #endif 01352 01353 } preference; 01354 01355 /* Decl'd in prefmem.c and needed in decide.c */ 01356 extern bool remove_preference_from_clones(preference * pref); 01357 01358 /* ------------------------------------------------------------------------ 01359 01360 Impasse Types 01361 01362 ------------------------------------------------------------------------ */ 01363 01364 #define NONE_IMPASSE_TYPE 0 /* no impasse */ 01365 #define CONSTRAINT_FAILURE_IMPASSE_TYPE 1 01366 #define CONFLICT_IMPASSE_TYPE 2 01367 #define TIE_IMPASSE_TYPE 3 01368 #define NO_CHANGE_IMPASSE_TYPE 4 01369 01370 /* ------------------------------------------------------------------------ 01371 Slots 01372 01373 Fields in a slot: 01374 01375 next, prev: used for a doubly-linked list of all slots for a certain 01376 identifier. 01377 01378 id, attr: identifier and attribute of the slot 01379 01380 wmes: header of a doubly-linked list of all wmes in the slot 01381 01382 acceptable_preference_wmes: header of doubly-linked list of all 01383 acceptable preference wmes in the slot. (This is only used for 01384 context slots.) 01385 01386 all_preferences: header of a doubly-linked list of all preferences 01387 currently in the slot 01388 01389 preferences[NUM_PREFERENCE_TYPES]: array of headers of doubly-linked 01390 lists, one for each possible type of preference. These store 01391 all the preferences, sorted into lists according to their types. 01392 Within each list, the preferences are sorted according to their 01393 match goal, with the pref. supported by the highest goal at the 01394 head of the list. 01395 01396 impasse_id: points to the identifier of the attribute impasse object 01397 for this slot. (NIL if the slot isn't impassed.) 01398 01399 isa_context_slot: TRUE iff this is a context slot 01400 01401 impasse_type: indicates the type of the impasse for this slot. This 01402 is one of NONE_IMPASSE_TYPE, CONSTRAINT_FAILURE_IMPASSE_TYPE, etc. 01403 01404 marked_for_possible_removal: TRUE iff this slot is on the list of 01405 slots that might be deallocated at the end of the current top-level 01406 phase. 01407 01408 changed: indicates whether the preferences for this slot have changed. 01409 For non-context slots, this is either NIL or a pointer to the 01410 corresponding dl_cons in changed_slots (see decide.c); for context 01411 slots, it's just a zero/nonzero flag. 01412 01413 acceptable_preference_changed: for context slots only; this is zero 01414 if no acceptable or require preference in this slot has changed; 01415 if one has changed, it points to a dl_cons. 01416 ------------------------------------------------------------------------ */ 01417 01418 typedef struct slot_struct { 01419 struct slot_struct *next, *prev; /* dll of slots for this id */ 01420 Symbol *id; /* id, attr of the slot */ 01421 Symbol *attr; 01422 wme *wmes; /* dll of wmes in the slot */ 01423 wme *acceptable_preference_wmes; /* dll of acceptable pref. wmes */ 01424 preference *all_preferences; /* dll of all pref's in the slot */ 01425 preference *preferences[NUM_PREFERENCE_TYPES]; /* dlls for each type */ 01426 Symbol *impasse_id; /* NIL if slot is not impassed */ 01427 bool isa_context_slot; 01428 byte impasse_type; 01429 bool marked_for_possible_removal; 01430 dl_cons *changed; /* for non-context slots: points to the corresponding 01431 dl_cons in changed_slots; for context slots: just 01432 zero/nonzero flag indicating slot changed */ 01433 dl_cons *acceptable_preference_changed; /* for context slots: either zero, 01434 or points to dl_cons if the slot 01435 has changed + or ! pref's */ 01436 } slot; 01437 01438 /* ------------------------------------------------------------------- 01439 Tests 01440 01441 Tests in conditions can be blank (null) tests, tests for equality 01442 with a variable or constant, or more complicated tests (such as 01443 not-equal tests, conjunctive tests, etc.). We use some bit twiddling 01444 here to minimize space. We use just a pointer to represent any kind 01445 of test. For blank tests, this is the NIL pointer. For equality tests, 01446 it points to the symbol referent of the test. For other kinds of tests, 01447 bit 0 of the pointer is set to 1, and the pointer (minus 1) points to 01448 a complex_test structure. (A field in the complex_test structure 01449 further indicates the type of the test.) 01450 ------------------------------------------------------------------- */ 01451 01452 typedef char *test; 01453 01454 #define test_is_blank_test(t) ((t)==NIL) 01455 #define test_is_complex_test(t) (((unsigned long)(t)) & 1) 01456 #define test_is_blank_or_equality_test(t) (! test_is_complex_test(t)) 01457 01458 #define make_blank_test() ((test)NIL) 01459 #define make_equality_test(sym) ((sym)->common.reference_count++, (test)(sym)) 01460 #define make_equality_test_without_adding_reference(sym) ((test)(sym)) 01461 #define make_blank_or_equality_test(sym_or_nil) \ 01462 ((sym_or_nil) ? make_equality_test(sym_or_nil) : make_blank_test() ) 01463 #define make_test_from_complex_test(ct) ((test) (((char *)(ct))+1)) 01464 01465 #define referent_of_equality_test(t) ((Symbol *) (t)) 01466 #define complex_test_from_test(t) ((complex_test *) (((char *)(t))-1)) 01467 01468 typedef struct complex_test_struct { 01469 byte type; /* see definitions below */ 01470 union test_info_union { 01471 Symbol *referent; /* for relational tests */ 01472 list *disjunction_list; /* for disjunction tests */ 01473 list *conjunct_list; /* for conjunctive tests */ 01474 } data; 01475 } complex_test; 01476 01477 /* types of the complex_test's */ 01478 /* WARNING -- none of these can be 254 or 255 -- see rete.c */ 01479 #define NOT_EQUAL_TEST 1 /* various relational tests */ 01480 #define LESS_TEST 2 01481 #define GREATER_TEST 3 01482 #define LESS_OR_EQUAL_TEST 4 01483 #define GREATER_OR_EQUAL_TEST 5 01484 #define SAME_TYPE_TEST 6 01485 #define DISJUNCTION_TEST 7 /* item must be one of a list of constants */ 01486 #define CONJUNCTIVE_TEST 8 /* item must pass each of a list of tests */ 01487 #define GOAL_ID_TEST 9 /* item must be a goal identifier */ 01488 #define IMPASSE_ID_TEST 10 /* item must be an impasse identifier */ 01489 01490 /* ------------------------------------------------------------------- 01491 Conditions 01492 01493 Conditions are used for two things: (1) to represent the LHS of newly 01494 entered productions (new SP's or chunks); and (2) to represent the 01495 instantiated LHS in production instantiations. 01496 01497 Fields in a condition: 01498 01499 type: indicates the type of condition: either POSITIVE_CONDITION, 01500 NEGATIVE_CONDITION, or CONJUNCTIVE_NEGATION_CONDITION. 01501 01502 already_in_tc: (reserved for use by the cond_is_in_tc() stuff in 01503 production.c) 01504 01505 next, prev: used for a doubly-linked list of all conditions on the 01506 LHS, or all subconditions of an NCC. 01507 01508 data.tests.id_test, data.tests.attr_test, data.tests.value_test: 01509 for positive and negative conditions, these are the three wme 01510 field tests for the condition. 01511 01512 test_for_acceptable_preference: for positive and negative conditions, 01513 this is TRUE iff the condition tests for acceptable preference wmes. 01514 01515 data.ncc.top, data.ncc.bottom: for NCC's, these point to the top and 01516 bottom of the subconditions likned list. 01517 01518 bt: for top-level positive conditions in production instantiations, 01519 this structure gives information for that will be used in backtracing. 01520 01521 reorder: (reserved for use by the reorderer) 01522 ------------------------------------------------------------------- */ 01523 01524 /* --- types of conditions --- */ 01525 #define POSITIVE_CONDITION 0 01526 #define NEGATIVE_CONDITION 1 01527 #define CONJUNCTIVE_NEGATION_CONDITION 2 01528 01529 /* --- info on conditions used for backtracing (and by the rete) --- */ 01530 typedef struct bt_info_struct { 01531 wme *wme; /* the actual wme that was matched */ 01532 goal_stack_level level; /* level (at firing time) of the id of the wme */ 01533 01534 preference *trace; /* preference for BT, or NIL */ 01535 01536 /* mvp 5-17-94 */ 01537 list *prohibits; /* list of prohibit prefs to backtrace through */ 01538 01539 } bt_info; 01540 01541 /* --- info on conditions used only by the reorderer --- */ 01542 typedef struct reorder_info_struct { 01543 list *vars_requiring_bindings; /* used only during reordering */ 01544 struct condition_struct *next_min_cost; /* used only during reordering */ 01545 } reorder_info; 01546 01547 /* --- info on positive and negative conditions only --- */ 01548 typedef struct three_field_tests_struct { 01549 test id_test; 01550 test attr_test; 01551 test value_test; 01552 } three_field_tests; 01553 01554 /* --- info on negated conjunctive conditions only --- */ 01555 typedef struct ncc_info_struct { 01556 struct condition_struct *top; 01557 struct condition_struct *bottom; 01558 } ncc_info; 01559 01560 /* --- finally, the structure of a condition --- */ 01561 typedef struct condition_struct { 01562 byte type; 01563 bool already_in_tc; /* used only by cond_is_in_tc stuff */ 01564 bool test_for_acceptable_preference; /* for pos, neg cond's only */ 01565 struct condition_struct *next, *prev; 01566 union condition_main_data_union { 01567 three_field_tests tests; /* for pos, neg cond's only */ 01568 ncc_info ncc; /* for ncc's only */ 01569 } data; 01570 bt_info bt; /* for top-level positive cond's: used for BT and by the rete */ 01571 reorder_info reorder; /* used only during reordering */ 01572 } condition; 01573 01574 /* ------------------------------------------------------------------- 01575 Right-Hand-Side Values 01576 01577 Values on the RHS of productions can be given by symbols 01578 (constants or variables), by Rete locations, by indices of variables 01579 not bound on the LHS, or by function calls. We use the low-order two 01580 bits of a pointer to differentiate between these types of values. 01581 01582 If the low-order bits are: the rhs_value is: 01583 00 a pointer to a symbol 01584 01 a pointer to a list (for a function call) 01585 10 a Rete location 01586 11 the index of an RHS unbound variable 01587 01588 For function calls, the list is a consed list whose first element is 01589 the rhs_function structure, and whose remaining elements are the 01590 arguments of the function call. (Each argument is an rhs_value.) 01591 01592 WARNING: part of rete.c relies on the the fact that two rhs_values 01593 representing the same symbol, reteloc, or unboundvar will be equal (==), 01594 while two representing the same funcall will not be equal (==). 01595 ------------------------------------------------------------------- */ 01596 01597 typedef char *rhs_value; 01598 01599 #define rhs_value_is_symbol(rv) ((((unsigned long)(rv)) & 3)==0) 01600 #define rhs_value_is_funcall(rv) ((((unsigned long)(rv)) & 3)==1) 01601 #define rhs_value_is_reteloc(rv) ((((unsigned long)(rv)) & 3)==2) 01602 #define rhs_value_is_unboundvar(rv) ((((unsigned long)(rv)) & 3)==3) 01603 01604 /* Warning: symbol_to_rhs_value() doesn't symbol_add_ref. The caller must 01605 do the reference count update */ 01606 #define symbol_to_rhs_value(sym) ((rhs_value) (sym)) 01607 #define funcall_list_to_rhs_value(fl) ((rhs_value) (((char *)(fl))+1)) 01608 #define reteloc_to_rhs_value(field_num,levels_up) \ 01609 ((rhs_value) ( (levels_up)<<4) + ((field_num)<<2) + 2 ) 01610 #define unboundvar_to_rhs_value(n) ((rhs_value) (((n)<<2) + 3)) 01611 01612 #define rhs_value_to_symbol(rv) ((Symbol *)(rv)) 01613 #define rhs_value_to_funcall_list(rv) ((list *) (((char *)(rv))-1)) 01614 #define rhs_value_to_reteloc_field_num(rv) ((((unsigned long)(rv))>>2) & 3) 01615 #define rhs_value_to_reteloc_levels_up(rv) ((((unsigned long)(rv))>>4)& 0xFFFF) 01616 #define rhs_value_to_unboundvar(rv) (((unsigned long)(rv))>>2) 01617 01618 /* ------------------------------------------------------------------- 01619 RHS Actions 01620 01621 Fields in an action: 01622 01623 next: points to the next action in a singly-linked list of all 01624 actions in the RHS. 01625 01626 type: indicates the type of action: usually this is MAKE_ACTION, 01627 but for function calls it is FUNCALL_ACTION. 01628 01629 preference_type: for make actions, this indicates the type of the 01630 preference being created: ACCEPTABLE_PREFERENCE_TYPE, etc. 01631 01632 support: indicates the compile-time calculated o-support of the action. 01633 This is either UNKNOWN_SUPPORT, O_SUPPORT, or I_SUPPORT. 01634 01635 already_in_tc: (reserved for use by compile-time o-support calcs) 01636 01637 id, attr: for make actions, these give the symbols (or Rete locations) 01638 for the id and attribute fields of the preference. 01639 01640 value: for MAKE_ACTION's, this gives the value field of the preference 01641 (a symbol or function call). For FUNCALL_ACTION's, this holds the 01642 function call itself. 01643 01644 referent: for MAKE_ACTION's of binary preferences, this gives the 01645 referent field of the preference. 01646 ------------------------------------------------------------------- */ 01647 01648 #define MAKE_ACTION 0 01649 #define FUNCALL_ACTION 1 01650 01651 #define UNKNOWN_SUPPORT 0 01652 #define O_SUPPORT 1 01653 #define I_SUPPORT 2 01654 01655 typedef struct action_struct { 01656 struct action_struct *next; 01657 byte type; 01658 byte preference_type; 01659 byte support; 01660 bool already_in_tc; /* used only by compile-time o-support calcs */ 01661 rhs_value id; 01662 rhs_value attr; 01663 rhs_value value; /* for FUNCALL_ACTION's, this holds the funcall */ 01664 rhs_value referent; 01665 } action; 01666 01667 /* ------------------------------------------------------------------- 01668 Productions 01669 01670 Fields in a production: 01671 01672 name: points to the name of the production (a symbol) 01673 01674 documentation: points to a string (a memory_block_for_string) giving 01675 user-provided documentation about the production, or NIL if the 01676 user didn't give any documentation for it. 01677 01678 reference_count: (see below) 01679 01680 firing_count: the number of times this production has ever fired 01681 since it was created. (Note that this is not reset by an init-soar.) 01682 01683 next, prev: used for a doubly-linked list of productions of the same 01684 type (see below). The list header is all_productions_of_type[]. 01685 01686 type: the type of the production: USER_PRODUCTION_TYPE, 01687 DEFAULT_PRODUCTION_TYPE, CHUNK_PRODUCTION_TYPE, or 01688 JUSTIFICATION_PRODUCTION_TYPE. 01689 01690 declared_support: indicates whether the production was declared 01691 :o-support or :i-support. This field is either UNDECLARED_SUPPORT, 01692 DECLARED_O_SUPPORT, or DECLARED_I_SUPPORT. 01693 01694 trace_firings: TRUE iff a (pwatch) has been set on this production. 01695 01696 p_node: If the production is currently in the Rete, this points to 01697 the corresponding p_node in the Rete. If the production is not in 01698 the Rete, this field is NIL. 01699 01700 action_list: singly-linked list of the RHS actions of the production. 01701 01702 rhs_unbound_variables: A (consed) list of variables used on the RHS 01703 that aren't bound on the LHS, in the order of their indices (for 01704 rhs_values). For chunks, this is NIL, since we discard chunk 01705 variable names. 01706 01707 instantiations: header for a doubly-linked list of the instantiations 01708 of this production that are currently in the match set (i.e., 01709 Rete-supported). 01710 01711 OPERAND_which_assert_list: (BUGBUG need info from REW or RCHONG) 01712 01713 interrupt: TRUE iff we should break when this production matches 01714 (but before it fires). Note: this functionality is 01715 only used when the compile time option: 01716 MATCHTIME_INTERRUPT is defined. 01717 01718 Reference counts on productions: 01719 +1 if it's in production memory (i.e., hasn't been excised) 01720 +1 for each existing instantiation pointing to it 01721 We deallocate a production if its reference_count goes to 0. 01722 ------------------------------------------------------------------- */ 01723 01724 #define UNDECLARED_SUPPORT 0 01725 #define DECLARED_O_SUPPORT 1 01726 #define DECLARED_I_SUPPORT 2 01727 01728 /* RCHONG: begin 10.11 */ 01729 01730 #define PE_PRODS 0 01731 #define IE_PRODS 1 01732 #define NO_SAVED_PRODS -1 01733 01734 /* RCHONG: end 10.11 */ 01735 01736 typedef struct production_struct { 01737 Symbol *name; 01738 char *documentation; /* pointer to memory block, or NIL */ 01739 char *filename; /* name of source file, or NIL. kjh CUSP(b11) */ 01740 unsigned long reference_count; 01741 unsigned long firing_count; /* how many times it's fired */ 01742 struct production_struct *next, *prev; /* used for dll */ 01743 byte type; 01744 byte declared_support; 01745 01746 #ifndef TRACE_CONTEXT_DECISIONS_ONLY 01747 bool trace_firings; /* used by pwatch */ 01748 #endif 01749 01750 struct rete_node_struct *p_node; /* NIL if it's not in the rete */ 01751 action *action_list; /* RHS actions */ 01752 list *rhs_unbound_variables; /* RHS vars not bound on LHS */ 01753 struct instantiation_struct *instantiations; /* dll of inst's in MS */ 01754 int OPERAND_which_assert_list; /* RCHONG: 10.11 */ 01755 byte interrupt; /* SW: 7.31.03 */ 01756 #ifdef BUG_139_WORKAROUND 01757 bool already_fired; /* RPM test workaround for bug #139 */ 01758 #endif 01759 } production; 01760 01761 /* ------------------------------------------------------------------- 01762 Instantiations and Nots 01763 01764 Instantiations record three main things: 01765 (1) the instantiated LHS of the production, 01766 (2) any "<>" tests that are between identifiers and that occur in 01767 top-level positive conditions on the LHS, and 01768 (3) the still-existing preferences that were generated by the RHS. 01769 01770 Fields in an instantiation: 01771 01772 prod: points to the production. (Note: this can also be NIL, for 01773 fake instantiations used for goal ^item augmentations. See decide.c.) 01774 01775 next, prev: used for a doubly-linked list of instantiations of this 01776 production that are still in the match set. 01777 01778 rete_token, rete_wme: these fields are reserved for use by the Rete. 01779 (The Rete needs them to find the proper instantiation to retract 01780 when a token is delted from a p_node.) 01781 01782 top_of_instantiated_conditions, bottom_of_instantiated_conditions: 01783 point to the top and bottom of the instantiated LHS conditions. 01784 01785 nots: header of a singly-linked list of Nots from the LHS. 01786 01787 preferences_generated: header for a doubly-linked list of existing 01788 preferences that were created by this instantiation. 01789 01790 match_goal: points to the match goal of the instantiation, or NIL 01791 if there is none. 01792 01793 match_goal_level: goal stack level of the match goal, or 01794 ATTRIBUTE_IMPASSE_LEVEL if there is no match goal. 01795 01796 okay_to_variablize: TRUE iff it's okay to variablize a 01797 chunk/justification formed by backtracing through this instantiation. 01798 This is used to make sure we don't variablize a chunk that got formed 01799 by backtracing through some other justification. 01800 01801 in_ms: TRUE iff this instantiation is still in the match set (i.e., 01802 Rete-supported). 01803 backtrace_number: used by the chunker to avoid backtracing through 01804 the same instantiation twice during the building of the same chunk. 01805 01806 GDS_evaluated_already: Most productions produce several actions. 01807 When we compute the goal-dependency-set (gds) gds for one wme of an 01808 instantiation, there's no point in redoing the work for a second wme 01809 from the same instantiation since the gds will be the same. By 01810 testing this flag, we avoid duplicating this work. The value is set 01811 to FALSE whenever an instantiation is created. 01812 01813 Reference counts on instantiations: 01814 +1 if it's in the match set 01815 +1 for each preference it created that's still around 01816 The reference count is kept implicitly using the preferences_generated 01817 and in_ms fields. We deallocate an instantiation if its reference count 01818 goes to 0. 01819 ------------------------------------------------------------------- */ 01820 01821 typedef struct not_struct { 01822 struct not_struct *next; /* next Not in the singly-linked list */ 01823 Symbol *s1; /* the two identifiers constrained to be "<>" */ 01824 Symbol *s2; 01825 } not; 01826 01827 typedef struct instantiation_struct { 01828 production *prod; 01829 struct instantiation_struct *next, *prev; /* dll of inst's from same prod */ 01830 struct token_struct *rete_token; /* used by Rete for retractions */ 01831 wme *rete_wme; /* ditto */ 01832 condition *top_of_instantiated_conditions; 01833 condition *bottom_of_instantiated_conditions; 01834 not *nots; 01835 preference *preferences_generated; /* header for dll of prefs */ 01836 Symbol *match_goal; /* symbol, or NIL if none */ 01837 goal_stack_level match_goal_level; /* level, or ATTRIBUTE_IMPASSE_LEVEL */ 01838 byte okay_to_variablize; 01839 bool in_ms; /* TRUE iff this inst. is still in the match set */ 01840 tc_number backtrace_number; 01841 bool GDS_evaluated_already; 01842 #if defined(WATCH_SSCI_INSTS) || defined(THIN_JUSTIFICATIONS) 01843 bool isa_ssci_inst; 01844 #endif 01845 } instantiation; 01846 01847 /* REW: begin 09.15.96 */ 01848 /* A dll of instantiations that will be used to determine the gds through 01849 a backtracing-style procedure, evaluate_gds in decide.c */ 01850 01851 typedef struct pi_struct { 01852 struct pi_struct *next, *prev; 01853 instantiation *inst; 01854 } parent_inst; 01855 /* REW: end 09.15.96 */ 01856 01857 /* ==================================================================== 01858 Global System Parameters and Related Definitions 01859 01860 A set of system parameters (sysparam's for short) affect many operations 01861 of Soar, including learning, tracing, deciding, etc. In order to 01862 provide a simple, uniform update mechanism (a single callback routine that 01863 gets called when any parameter changes), we store these parameters in 01864 an array sysparams[]. Below, we #define various indices into this array 01865 corresponding to various system parameters. 01866 01867 Most of the parameters are of type "long". A few parameters are more 01868 naturally handled as lists; for these, the array value is just a dummy, 01869 and callback routines must inspect a global variable to get the real 01870 value. Chunk_free_problem_spaces is an example of this. 01871 01872 The array of sysparams[] can be read directly, but should be modified 01873 ONLY via calls to set_sysparam(), which is defined in init-soar.c. 01874 ==================================================================== */ 01875 01876 /* ------------------------------- 01877 Types of Productions 01878 ------------------------------- */ 01879 01880 #define USER_PRODUCTION_TYPE 0 01881 #define DEFAULT_PRODUCTION_TYPE 1 01882 #define CHUNK_PRODUCTION_TYPE 2 01883 #define JUSTIFICATION_PRODUCTION_TYPE 3 01884 01885 #define NUM_PRODUCTION_TYPES 4 01886 01887 /* --------------------------------------- 01888 Match Set print parameters 01889 --------------------------------------- */ 01890 01891 #define MS_ASSERT_RETRACT 0 /* print both retractions and assertions */ 01892 #define MS_ASSERT 1 /* print just assertions */ 01893 #define MS_RETRACT 2 /* print just retractions */ 01894 01895 typedef byte ms_trace_type; /* must be one of the above constants */ 01896 01897 /* --------------------------------------- 01898 How much information to print about 01899 the wmes matching an instantiation 01900 --------------------------------------- */ 01901 01902 #define NONE_WME_TRACE 1 /* don't print anything */ 01903 #define TIMETAG_WME_TRACE 2 /* print just timetag */ 01904 #define FULL_WME_TRACE 3 /* print whole wme */ 01905 #define NO_WME_TRACE_SET 4 01906 01907 typedef byte wme_trace_type; /* must be one of the above constants */ 01908 01909 /* ------------------------------- 01910 Ways to Do User-Select 01911 ------------------------------- */ 01912 01913 #define USER_SELECT_FIRST 0 /* just choose the first candidate item */ 01914 #define USER_SELECT_ASK 1 /* ask the user */ 01915 #define USER_SELECT_RANDOM 2 /* pick one at random */ 01916 #define USER_SELECT_LAST 3 /* choose the last item AGR 615 */ 01917 01918 /* --------------------------- 01919 And now, the sysparam's 01920 --------------------------- */ 01921 01922 /* ====== Sysparams for what to trace === */ 01923 01924 #define TRACE_CONTEXT_DECISIONS_SYSPARAM 1 01925 #define TRACE_PHASES_SYSPARAM 2 01926 01927 /* --- Warning: these next four MUST be consecutive and in the order of the 01928 production types defined above --- */ 01929 #define TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM 3 01930 #define TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM 4 01931 #define TRACE_FIRINGS_OF_CHUNKS_SYSPARAM 5 01932 #define TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM 6 01933 01934 #define TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM 7 01935 #define TRACE_FIRINGS_PREFERENCES_SYSPARAM 8 01936 #define TRACE_WM_CHANGES_SYSPARAM 9 01937 #define TRACE_CHUNK_NAMES_SYSPARAM 10 01938 #define TRACE_JUSTIFICATION_NAMES_SYSPARAM 11 01939 #define TRACE_CHUNKS_SYSPARAM 12 01940 #define TRACE_JUSTIFICATIONS_SYSPARAM 13 01941 #define TRACE_BACKTRACING_SYSPARAM 14 01942 /* ===== watch loading flag ===== KJC 7/96 */ 01943 #define TRACE_LOADING_SYSPARAM 15 01944 01945 /* ====== Max Elaborations === */ 01946 #define MAX_ELABORATIONS_SYSPARAM 16 01947 01948 /* ====== Max Chunks === */ 01949 #define MAX_CHUNKS_SYSPARAM 17 01950 01951 #define RESPOND_TO_LOAD_ERRORS_SYSPARAM 18 01952 01953 /* ====== Sysparams for control of learning === */ 01954 #define LEARNING_ON_SYSPARAM 19 01955 #define LEARNING_ONLY_SYSPARAM 20 01956 #define LEARNING_EXCEPT_SYSPARAM 21 01957 #define LEARNING_ALL_GOALS_SYSPARAM 22 01958 01959 /* ====== User Select === */ 01960 #define USER_SELECT_MODE_SYSPARAM 23 01961 01962 /* ====== Print Warnings === */ 01963 #define PRINT_WARNINGS_SYSPARAM 24 01964 01965 /* AGR 627 begin */ 01966 /* ====== Whether to print out aliases as they're defined === */ 01967 #define PRINT_ALIAS_SYSPARAM 25 01968 /* AGR 627 end */ 01969 01970 /* ===== explain_flag ===== KJC 7/96 */ 01971 #define EXPLAIN_SYSPARAM 26 01972 01973 /* kjh(B14) */ 01974 #define USE_LONG_CHUNK_NAMES 27 01975 01976 /* REW: 10.22.97 */ 01977 #define TRACE_OPERAND2_REMOVALS_SYSPARAM 28 01978 01979 /* RMJ */ 01980 #define REAL_TIME_SYSPARAM 29 01981 01982 /* RMJ */ 01983 #define ATTENTION_LAPSE_ON_SYSPARAM 30 01984 01985 /* SAN */ 01986 #define TRACE_INDIFFERENT_SYSPARAM 31 01987 01988 /* --- Warning: if you add sysparams, be sure to update the next line! --- */ 01989 #define HIGHEST_SYSPARAM_NUMBER 31 01990 01991 /* ----------------------------------------- 01992 Sysparams[] stores the parameters; set_sysparam() 01993 should be used to modify them. 01994 ----------------------------------------- */ 01995 01996 extern void init_sysparams(void); 01997 extern void set_sysparam(int param_number, long new_value); 01998 01999 #ifndef MAXPATHLEN /* excludeFromBuildInfo */ 02000 #define MAXPATHLEN 1024 /* AGR 536 - from sys/param.h */ 02001 #endif 02002 02003 #define kChunkNamePrefixMaxLength 64 /* kjh (B14) */ 02004 02005 /****************************************************************** 02006 ****************************************************************** 02007 Subroutine Declarations 02008 ****************************************************************** 02009 ******************************************************************/ 02010 02011 /* ======================================================================== 02012 main.c and init_soar.c 02013 ======================================================================== */ 02014 02015 extern void reset_statistics(void); 02016 extern void setup_signal_handling(void); 02017 extern void load_init_file(void); 02018 02019 /* --- signal handler that gets invoked on SIGINT --- */ 02020 extern void control_c_handler(int the_signal); 02021 02022 /* --------------------------------------------------------------------- 02023 Exiting Soar 02024 02025 Exit_soar() and abort_with_fatal_error() both terminate Soar, closing 02026 the log file before exiting. Abort_with_fatal_error() also prints 02027 an error message before exiting. Just_before_exit_soar() calls the 02028 Soar cleanup functions but does not actually exit. This is useful 02029 for interfaces that do their own exiting. 02030 --------------------------------------------------------------------- */ 02031 02032 extern void exit_soar(void); 02033 extern void abort_with_fatal_error(char *); 02034 extern void just_before_exit_soar(void); 02035 02036 /* --------------------------------------------------------------------- 02037 Timer Utility Routines 02038 02039 These are utility routines for using timers. We use (struct timeval)'s 02040 (defined in a system include file) for keeping track of the cumulative 02041 time spent in one part of the system or another. Reset_timer() 02042 clears a timer to 0. Start_timer() and stop_timer() are used for 02043 timing an interval of code--the usage is: 02044 02045 start_timer (&timeval_to_record_the_start_time_in); 02046 ... other code here ... 02047 stop_timer (&timeval_to_record_the_start_time_in, 02048 &timeval_holding_accumulated_time_for_this_code); 02049 02050 Finally, timer_value() returns the accumulated value of a timer 02051 (in seconds). 02052 --------------------------------------------------------------------- */ 02053 02054 #ifndef NO_TIMING_STUFF 02055 02056 extern void reset_timer(TIMER_VALUE * tv_to_reset); 02057 extern void start_timer(TIMER_VALUE * tv_for_recording_start_time); 02058 extern void stop_timer(TIMER_VALUE * tv_with_recorded_start_time, TIMER_VALUE * tv_with_accumulated_time); 02059 extern double timer_value(TIMER_VALUE * tv); 02060 extern int test_timers(); 02061 02062 #else /* NO_TIMING_STUFF */ 02063 02064 #define start_timer(X) 02065 #define stop_timer(X) 02066 #endif 02067 02068 #define ONE_MILLION (1000000) 02069 02070 #ifdef REAL_TIME_BEHAVIOR 02071 /* RMJ */ 02072 extern void init_real_time(); 02073 extern struct timeval *current_real_time; 02074 #endif 02075 02076 #ifdef ATTENTION_LAPSE 02077 /* RMJ */ 02078 extern void wake_from_attention_lapse(); 02079 extern void init_attention_lapse(); 02080 #endif 02081 02082 /* --------------------------------------------------------------------- 02083 Adding and Removing Pwatchs 02084 02085 Productions_being_traced is a (consed) list of all productions 02086 on which a pwatch has been set. Pwatchs are added/removed via 02087 calls to add_pwatch() and remove_pwatch(). 02088 --------------------------------------------------------------------- */ 02089 02090 extern void add_pwatch(struct production_struct *prod); 02091 extern void remove_pwatch(struct production_struct *prod); 02092 02093 /* --------------------------------------------------------------------- 02094 Reinitializing Soar 02095 02096 Reinitialize_soar() does all the work for an init-soar. 02097 --------------------------------------------------------------------- */ 02098 02099 extern void reinitialize_soar(void); 02100 02101 /* --------------------------------------------------------------------- 02102 Running Soar 02103 02104 Each of the following routines runs Soar for a certain duration, 02105 or until stop_soar gets set to TRUE. 02106 - Run_forever() runs Soar forever. 02107 - Run_for_n_phases() runs Soar for a given number (n) of top-level 02108 phases. (If n==-1, it runs forever.) 02109 - Run_for_n_elaboration_cycles() runs Soar for a given number (n) 02110 of elaboration cycles. (Here, decision phase is counted as 02111 an elaboration cycle.) (If n==-1, it runs forever.) 02112 - Run_for_n_decision_cycles() runs Soar for a given number (n) of 02113 decision cycles. (If n==-1, it runs forever.) 02114 - Run_for_n_modifications_of_output runs soar by decision cycle 02115 n times, where n starts at 0 and is incremented anytime the 02116 output link is modified by the agent. n is not incremented when 02117 the output-link is created nor when the output-link is modified 02118 during the Input Cycle, ie when getting feedback from a simulator. 02119 - Run_for_n_selections_of_slot (long n, Symbol *attr_of_slot): this 02120 runs Soar until the nth time a selection is made for a given 02121 type of slot. Attr_of_slot should be either state_symbol or 02122 operator_symbol. 02123 - Run_for_n_selections_of_slot_at_level (long n, Symbol *attr_of_slot, 02124 goal_stack_level level): this runs Soar for n selections of the 02125 given slot at the given level, or until the goal stack is popped 02126 so that level no longer exists. 02127 --------------------------------------------------------------------- */ 02128 02129 enum go_type_enum { GO_PHASE, GO_ELABORATION, GO_DECISION, 02130 GO_STATE, GO_OPERATOR, GO_SLOT, GO_OUTPUT 02131 }; 02132 02133 extern void run_forever(void); 02134 extern void run_for_n_phases(long n); 02135 extern void run_for_n_elaboration_cycles(long n); 02136 extern void run_for_n_decision_cycles(long n); 02137 extern void run_for_n_modifications_of_output(long n); 02138 extern void run_for_n_selections_of_slot(long n, Symbol * attr_of_slot); 02139 extern void run_for_n_selections_of_slot_at_level(long n, Symbol * attr_of_slot, goal_stack_level level); 02140 02141 /* REW: begin 05.05.97 */ 02142 /* Added new DETERMINE_LEVEL_PHASE here and in the timers */ 02143 02144 enum top_level_phase { INPUT_PHASE, DETERMINE_LEVEL_PHASE, PREFERENCE_PHASE, WM_PHASE, 02145 OUTPUT_PHASE, DECISION_PHASE 02146 }; 02147 /* REW: end 05.05.97 */ 02148 02149 /* ======================================================================= 02150 wmem.c 02151 02152 Working Memory Management and Utility Routines 02153 02154 Reset_wme_timetags() resets the wme timetag generator back to 1. 02155 This should be called during an init-soar. 02156 02157 Make_wme() creates and returns a new wme. The caller should add the 02158 wme onto the appropriate dll (e.g., my_slot->wmes) and should call 02159 add_wme_to_wm() on it. 02160 02161 Add_wme_to_wm() and remove_wme_from_wm() make changes to WM. Again, 02162 the caller is responsible for manipulating the appropriate dll. WM 02163 changes don't actually get stuffed down the rete until the end of the 02164 phase, when do_buffered_wm_and_ownership_changes() gets be called. 02165 02166 Remove_wme_list_from_wm() is a utility routine that scans through a 02167 list of wmes, linked by their "next" fields, and calls remove_wme_from_wm() 02168 on each one. 02169 02170 Wme_add_ref() and wme_remove_ref() are macros for incrementing and 02171 decrementing the reference count on a wme. Deallocate_wme() deallocates 02172 a wme; this should only be invoked via the wme_remove_ref() macro. 02173 02174 Find_name_of_object() is a utility function for finding the value of 02175 the ^name attribute on a given object (symbol). It returns the name, 02176 or NIL if the object has no name. 02177 ======================================================================= */ 02178 02179 extern void reset_wme_timetags(void); 02180 extern wme *make_wme(Symbol * id, Symbol * attr, Symbol * value, bool acceptable); 02181 extern void add_wme_to_wm(wme * w); 02182 extern void remove_wme_from_wm(wme * w); 02183 extern void remove_wme_list_from_wm(wme * w); 02184 extern void do_buffered_wm_changes(void); 02185 02186 #define wme_add_ref(w) { (w)->reference_count++; } 02187 #define wme_remove_ref(w) { \ 02188 (w)->reference_count--; \ 02189 if ((w)->reference_count == 0) deallocate_wme(w); } 02190 02191 extern void deallocate_wme(wme * w); 02192 extern Symbol *find_name_of_object(Symbol * id); 02193 02194 /* ======================================================================= 02195 decide.c 02196 02197 Decide.c contains the decider as well as routine for managing working 02198 memory, preference memory, slots, and the garbage collection of 02199 disconnected WMEs. 02200 02201 Whenever a link is added from one identifier to another (i.e., 02202 (I37 ^x R26)), we call post_link_addition(). This records the link 02203 addition and buffers it for later processing. Similarly, whenever a 02204 link is removed, we call post_link_removal(), which buffers the 02205 removal for later processing. At the end of the phase, we call 02206 do_buffered_link_changes() to update the goal stack level of all 02207 identifiers, and garbage collect anything that's now disconnected. 02208 02209 Whenever some acceptable or require preference for a context slot 02210 changes, we call mark_context_slot_as_acceptable_preference_changed(). 02211 02212 see decide.c for more information in the comments. 02213 ======================================================================= */ 02214 02215 extern void post_link_addition(Symbol * from, Symbol * to); 02216 extern void post_link_removal(Symbol * from, Symbol * to); 02217 02218 extern void mark_context_slot_as_acceptable_preference_changed(slot * s); 02219 02220 /* --------------------------------------------------------------------- 02221 Slot Management Routines (in tempmem.c) 02222 02223 Find_slot() looks for an existing slot for a given id/attr pair, and 02224 returns it if found. If no such slot exists, it returns NIL. 02225 Make_slot() looks for an existing slot for a given id/attr pair, 02226 returns it if found, and otherwise creates a new slot and returns it. 02227 02228 Mark_slot_as_changed() is called by the preference manager whenever 02229 the preferences for a slot change. This updates the list of 02230 changed_slots and highest_goal_whose_context_changed for use by the 02231 decider. 02232 02233 Old slots are garbage collected as follows: whenever we notice that 02234 the last preference has been removed from a slot, we call 02235 mark_slot_for_possible_removal(). We don't deallocate the slot 02236 right away, because there might still be wmes in it, or we might 02237 be about to add a new preference to it (through some later action 02238 of the same production firing, for example). At the end of the phase, 02239 we call remove_garbage_slots(), which scans through each marked slot 02240 and garbage collects it if it has no wmes or preferences. 02241 --------------------------------------------------------------------- */ 02242 02243 extern slot *find_slot(Symbol * id, Symbol * attr); 02244 extern slot *make_slot(Symbol * id, Symbol * attr); 02245 extern void mark_slot_as_changed(slot * s); 02246 extern void mark_slot_for_possible_removal(slot * s); 02247 extern void remove_garbage_slots(void); 02248 02249 /* --------------------------------------------------------------------- 02250 Preference Management Routines 02251 02252 Make_preference() creates a new preference structure of the given type 02253 with the given id/attribute/value/referent. (Referent is only used 02254 for binary preferences.) The preference is not yet added to preference 02255 memory, however. 02256 02257 Preference_add_ref() and preference_remove_ref() are macros for 02258 incrementing and decrementing the reference count on a preference. 02259 02260 Possibly_deallocate_preference_and_clones() checks whether a given 02261 preference and all its clones have reference_count 0, and deallocates 02262 them all if they do; it returns TRUE if they were actually deallocated, 02263 FALSE otherwise. Deallocate_preference() deallocates a given 02264 preference. These routines should normally be invoked only via the 02265 preference_remove_ref() macro. 02266 02267 Add_preference_to_tm() adds a given preference to preference memory (and 02268 hence temporary memory). Remove_preference_from_tm() removes a given 02269 preference from PM and TM. 02270 02271 Process_o_rejects_and_deallocate_them() handles the processing of 02272 o-supported reject preferences. This routine is called from the firer 02273 and passed a list of all the o-rejects generated in the current 02274 preference phase (the list is linked via the "next" fields on the 02275 preference structures). This routine removes all preferences for 02276 matching values from TM, and deallocates the o-reject preferences when 02277 done. 02278 --------------------------------------------------------------------- */ 02279 02280 extern preference *make_preference(byte type, Symbol * id, Symbol * attr, Symbol * value, Symbol * referent); 02281 02282 #define preference_add_ref(p) { (p)->reference_count++; } 02283 #define preference_remove_ref(p) { \ 02284 (p)->reference_count--; \ 02285 if ((p)->reference_count == 0) \ 02286 possibly_deallocate_preference_and_clones(p); } 02287 02288 extern bool possibly_deallocate_preference_and_clones(preference * pref); 02289 extern void deallocate_preference(preference * pref); 02290 02291 extern void add_preference_to_tm(preference * pref); 02292 extern void remove_preference_from_tm(preference * pref); 02293 extern void process_o_rejects_and_deallocate_them(preference * o_rejects); 02294 02295 /* --------------------------------------------------------------------- 02296 Top-Level Decider Routines 02297 02298 Init_decider() should be called at startup time to initialize this 02299 module. 02300 02301 Do_buffered_wm_and_ownership_changes() does the end-of-phase processing 02302 of WM changes, ownership calculations, garbage collection, etc. 02303 02304 Do_working_memory_phase() and do_decision_phase() are called from 02305 the top level to run those phases. 02306 02307 Create_top_goal() creates the top goal in the goal stack. 02308 Clear_goal_stack() wipes out the whole goal stack--this is called 02309 during an init-soar. 02310 02311 Print_lowest_slot_in_context_stack() is used for the watch 0 trace 02312 to print the context slot that was just decided. 02313 --------------------------------------------------------------------- */ 02314 02315 extern void init_decider(void); 02316 extern void do_buffered_wm_and_ownership_changes(void); 02317 extern void do_working_memory_phase(void); 02318 extern void do_decision_phase(void); 02319 extern void create_top_goal(void); 02320 extern void clear_goal_stack(void); 02321 extern void print_lowest_slot_in_context_stack(void); 02322 02323 /* ================================================================= 02324 interface.c 02325 02326 This portion of the code is normally replaced by the Tcl interface 02327 and interface support routines, but some maintenance continues, in 02328 the event someone needs to build a version without Tcl. However some 02329 user interface commands are likely to break or give unusual output. 02330 02331 User Interface Command Routines: 02332 02333 Each user interface command has a corresponding function 02334 (user_interface_routine) to handle it. These commands/functions 02335 should be installed at system startup time via add_command(). The 02336 command name string passed to add_command() must be permanently 02337 available (e.g., a constant in global data memory). 02338 02339 When a user interface routine is called, the current lexeme is the 02340 command name. The function should call the lexer to read its arguments, 02341 etc. If successful, the function should return TRUE and should exit 02342 with the current lexeme being the closing right parenthesis (otherwise 02343 the dispatching function will print an error message about extra 02344 arguments being given). If unsuccessful, the function should 02345 return FALSE. 02346 02347 Dispatching commands: 02348 02349 Dispatch_command() dispatches the appropriate user interface routine 02350 for the current command (i.e., the command named by the current lexeme). 02351 It calls set_lexer_allow_ids(TRUE) before dispatching the command, 02352 so if the command doesn't allow id's, it should call 02353 set_lexer_allow_ids(FALSE) immediately. Dispatch_command() returns 02354 TRUE if the command was successful, FALSE if any error occurred. 02355 02356 Repeatedly_read_and_dispatch_commands() keeps calling dispatch_command() 02357 until end-of-file is reached on the current input file. 02358 02359 Load_file() sets up the lexer to read from a given open file, executes 02360 all the commands in that file, and then restore the lexer to reading 02361 the previous file. 02362 02363 Help Information: 02364 02365 Add_help() should be called at system startup time to specify to the 02366 "help" command what help info is available. It takes a topic name and 02367 an array of lines of text for the helpscreen. All these strings 02368 should be permanently available (e.g., constants in global data memory). 02369 ================================================================= */ 02370 02371 typedef bool(*user_interface_routine) (void); 02372 extern void add_command(char *command_name, user_interface_routine f); 02373 02374 extern bool dispatch_command(void); 02375 02376 extern void repeatedly_read_and_dispatch_commands(void); 02377 02378 extern void load_file(char *file_name, FILE * already_open_file); 02379 02380 extern void add_help(char *topic, char **lines_of_text); 02381 02382 extern void init_built_in_commands(void); 02383 02384 extern void init_multi_agent_built_in_commands(void); 02385 02386 extern bool old_parse_go_command(void); 02387 extern void old_execute_go_selection(void); 02388 02389 /* this routine is defined in interface.c, but the Symbol struct 02390 hasn't been defined yet, so we can't declare it yet. So kjc 02391 moved this prototype to ? ? ? 02392 extern Symbol *read_identifier_or_context_variable (void); 02393 */ 02394 02395 extern void respond_to_load_errors(void); 02396 02397 /* defined in tilde.c but also used in interface.c */ 02398 extern char *tilde_expand(char *filename); 02399 02400 /* AGR 568 begin */ 02401 typedef struct expansion_node { 02402 struct lexeme_info lexeme; 02403 struct expansion_node *next; 02404 } expansion_node; 02405 02406 typedef struct alias_struct { 02407 char *alias; 02408 struct expansion_node *expansion; 02409 struct alias_struct *next; 02410 } alias_struct; 02411 02412 typedef struct dir_stack_struct { 02413 char *directory; 02414 struct dir_stack_struct *next; 02415 } dir_stack_struct; 02416 /* AGR 568 end */ 02417 02418 /* AGR 568 This bug fix concerned an alias command. But I've expanded 02419 it a little to also include the pushd and popd commands, which are 02420 all being implemented for the release of 6.2. 11-May-94 */ 02421 02422 /* ====================================================================== 02423 parser.c 02424 02425 The Production (SP) Parser 02426 02427 Init_parser() should be called at startup time. Parse_production() 02428 reads an SP (starting from the production name), builds a production, 02429 adds it to the rete, and returns a pointer to the new production 02430 (or NIL if any error occurred). Parse_lhs() reads just an LHS, 02431 and returns a condition list (or NIL if an error occurred). 02432 Parse_rhs() reads an RHS, setting "dest_rhs" to point to the resulting 02433 action list; it returns TRUE if successful, FALSE if any error occurred. 02434 ====================================================================== */ 02435 02436 extern void init_parser(void); 02437 extern condition *parse_lhs(void); 02438 extern bool parse_rhs(action ** dest_rhs); 02439 extern struct production_struct *parse_production(void); 02440 02441 /* ====================================================================== 02442 print.c 02443 02444 Printing with an Optional Log File and with Redirection to a File 02445 02446 We want to print stuff not only to the screen but also to a log 02447 file (if one is currently being used). The print_string(), print(), 02448 print_with_symbols(), and print_spaces() routines do this. 02449 02450 Start_log_file() and stop_log_file() open and close the current log 02451 file. Print_string_to_log_file_only() is called by the lexer to 02452 echo keyboard input to the log file (it's already on the screen, so 02453 we don't want to print it there too). 02454 02455 Print_string() and print_spaces() do the obvious things. 02456 Print() is exactly like printf() in C, except it prints to both 02457 the screen and log file (if there is one). Print_with_symbols() 02458 is sort of like print, but only takes two kinds of escape sequences 02459 in the format string: 02460 %y -- print a symbol 02461 %% -- print a "%" sign 02462 02463 Sometimes we need to know the current output column so we can put 02464 a line break in the right place. Get_printer_output_column() returns 02465 the current column number (1 means the start of the line). 02466 Tell_printer_that_output_column_has_been_reset () is called from the 02467 lexer every time it reads a line from the keyboard--since after the 02468 user types a line (and hits return) the output column is reset. 02469 02470 We also support temporarily redirecting all printing output to 02471 another file. This is done by calling start_redirection_to_file() 02472 and stop_redirection_to_file(). In between these calls, all screen 02473 and log file output is turned off, and printing is done only to the 02474 redirection file. 02475 ====================================================================== */ 02476 02477 extern void start_log_file(char *filename, bool append); 02478 extern void stop_log_file(void); 02479 extern void print_string_to_log_file_only(char *string); 02480 02481 extern int get_printer_output_column(void); 02482 extern void tell_printer_that_output_column_has_been_reset(void); 02483 02484 extern void start_redirection_to_file(FILE * already_opened_file); 02485 extern void stop_redirection_to_file(void); 02486 02487 extern void print_string(char *s); 02488 #ifdef USE_STDARGS 02489 extern void print(char *format, ...); 02490 extern void print_with_symbols(char *format, ...); 02491 #else 02492 extern void print(); 02493 extern void print_with_symbols(); 02494 #endif 02495 extern void print_spaces(int n); 02496 02497 /* ------------------------------------------------------------------------ 02498 String to Escaped String Conversion 02499 {Symbol, Test, RHS Value} to String Conversion 02500 02501 These routines produce strings. Each takes an optional parameter "dest" 02502 which, if non-nil, points to the destination buffer for the result string. 02503 If dest is nil, these routines use a global buffer, and return a pointer 02504 to it. (Otherwise "dest" itself is returned.) Note that a single global 02505 buffer is shared by all three routines, so callers should assume the 02506 buffer will be destroyed by the next call to these routines with dest=NIL. 02507 02508 String_to_escaped_string() takes a string and a first/last char, 02509 and produces an "escaped string" representation of the string; i.e., 02510 a string that uses '\' escapes to include special characters. 02511 For example, input 'ab"c' with first/last character '"' yields 02512 '"ab\"c"'. This is used for printing quoted strings and for printing 02513 symbols using |vbar| notation. 02514 02515 Symbol_to_string() converts a symbol to a string. The "rereadable" 02516 parameter indicates whether a rereadable representation is desired. 02517 Normally symbols are printed rereadably, but for (write) and Text I/O, 02518 we don't want this. 02519 02520 Test_to_string() takes a test and produces a string representation. 02521 02522 Rhs_value_to_string() takes an rhs_value and produces a string 02523 representation. The rhs_value MUST NOT be a reteloc. 02524 ----------------------------------------------------------------------- */ 02525 02526 extern char *string_to_escaped_string(char *s, char first_and_last_char, char *dest); 02527 extern char *symbol_to_string(Symbol * sym, bool rereadable, char *dest, size_t dest_size); 02528 extern char *test_to_string(test t, char *dest, size_t dest_size); 02529 extern char *rhs_value_to_string(rhs_value rv, char *dest, size_t dest_size); 02530 02531 /* ----------------------------------------------------------------------- 02532 Print Condition List, Action List, Production 02533 02534 Print_condition_list() prints a list of conditions. The "indent" 02535 parameter tells how many spaces to indent each line other than the 02536 first--the first line is not indented (the caller must handle this). 02537 The last line is printed without a trailing linefeed. The "internal" 02538 parameter, if TRUE, indicates that the condition list should be printed 02539 in internal format--one condition per line, without grouping all the 02540 conditions for the same id into one line. 02541 02542 Print_action_list() is similar except it prints actions instead of 02543 conditions. The actions MUST NOT contain any reteloc's. 02544 02545 Print_production() prints a given production, optionally using internal 02546 format. 02547 ----------------------------------------------------------------------- */ 02548 02549 extern void print_condition_list(condition * conds, int indent, bool internal); 02550 extern void print_action_list(action * actions, int indent, bool internal); 02551 extern void print_production(production * p, bool internal); 02552 02553 /* ----------------------------------------------------------------------- 02554 Other Printing Utilities 02555 02556 Print_condition() prints a single condition. Print_action() prints 02557 a single action (which MUST NOT contain any reteloc's). 02558 Note that these routines work by calling print_condition_list() and 02559 print_action_list(), respectively, so they print a linefeed if the 02560 output would go past COLUMNS_PER_LINE. 02561 02562 Preference_type_indicator() returns a character corresponding to 02563 a given preference type (byte)--for example, given BEST_PREFERENCE_TYPE, 02564 it returns '>'. 02565 02566 Print_preference() prints a given preference. Print_wme() prints a 02567 wme (including the timetag). Print_instantiation_with_wmes() prints 02568 an instantiation's production name and the wmes it matched, using a 02569 given wme_trace_type (e.g., TIMETAG_WME_TRACE). 02570 ----------------------------------------------------------------------- */ 02571 02572 extern void print_condition(condition * cond); 02573 extern void print_action(action * a); 02574 extern char preference_type_indicator(byte type); 02575 extern void print_preference(preference * pref); 02576 extern void print_wme(wme * w); 02577 02578 extern void print_instantiation_with_wmes(instantiation * inst, wme_trace_type wtt); 02579 02580 extern void print_list_of_conditions(condition * cond); /* BUGBUG comments */ 02581 02582 /* ======================================================================== 02583 production.c 02584 02585 Various utility routines for manipulating productions and parts thereof. 02586 Also includes the reorderer and compile-time o-support calculations. 02587 02588 Init_production_utilities() should be called before anything else here. 02589 ======================================================================== */ 02590 02591 /* This structure is used to break ties in favor of non-multi-attributes */ 02592 typedef struct multi_attributes_struct { 02593 Symbol *symbol; 02594 long value; 02595 struct multi_attributes_struct *next; 02596 } multi_attribute; 02597 02598 extern void init_production_utilities(void); 02599 02600 /* ------------------------------------------ */ 02601 /* Utilities for symbols and lists of symbols */ 02602 /* ------------------------------------------ */ 02603 02604 /* --- Looks at a symbol, returns appropriate first letter for a dummy 02605 variable or identifier to follow it. Returns '*' if none found. --- */ 02606 extern char first_letter_from_symbol(Symbol * sym); 02607 02608 /* --- Takes a list of symbols and returns a copy of the same list, 02609 incrementing the reference count on each symbol in the list. --- */ 02610 extern list *copy_symbol_list_adding_references(list * sym_list); 02611 02612 /* --- Frees a list of symbols, decrementing their reference counts. --- */ 02613 extern void deallocate_symbol_list_removing_references(list * sym_list); 02614 02615 /* ------------------- */ 02616 /* Utilities for tests */ 02617 /* ------------------- */ 02618 02619 extern void add_all_variables_in_action(action * a, tc_number tc, list ** var_list); 02620 extern void add_bound_variables_in_test(test t, tc_number tc, list ** var_list); 02621 extern void add_bound_variables_in_condition(condition * c, tc_number tc, list ** var_list); 02622 extern void unmark_variables_and_free_list(list * var_list); 02623 02624 /* --- Takes a test and returns a new copy of it. --- */ 02625 extern test copy_test(test t); 02626 02627 /* --- Same as copy_test(), only it doesn't include goal or impasse tests 02628 in the new copy. The caller should initialize the two flags to FALSE 02629 before calling this routine; it sets them to TRUE if it finds a goal 02630 or impasse test. --- */ 02631 extern test copy_test_removing_goal_impasse_tests(test t, bool * removed_goal, bool * removed_impasse); 02632 02633 /* --- Deallocates a test. --- */ 02634 extern void deallocate_test(test t); 02635 02636 /* --- Destructively modifies the first test (t) by adding the second 02637 one (add_me) to it (usually as a new conjunct). The first test 02638 need not be a conjunctive test. --- */ 02639 extern void add_new_test_to_test(test * t, test add_me); 02640 02641 /* --- Same as above, only has no effect if the second test is already 02642 included in the first one. --- */ 02643 extern void add_new_test_to_test_if_not_already_there(test * t, test add_me); 02644 02645 /* --- Returns TRUE iff the two tests are identical. --- */ 02646 extern bool tests_are_equal(test t1, test t2); 02647 02648 /* --- Returns a hash value for the given test. --- */ 02649 extern unsigned long hash_test(test t); 02650 02651 /* --- Returns TRUE iff the test contains an equality test for the given 02652 symbol. If sym==NIL, returns TRUE iff the test contains any equality 02653 test. --- */ 02654 extern bool test_includes_equality_test_for_symbol(test t, Symbol * sym); 02655 02656 /* --- Looks for goal or impasse tests (as directed by the two flag 02657 parameters) in the given test, and returns TRUE if one is found. --- */ 02658 extern bool test_includes_goal_or_impasse_id_test(test t, bool look_for_goal, bool look_for_impasse); 02659 02660 /* --- Looks through a test, and returns a new copy of the first equality 02661 test it finds. Signals an error if there is no equality test in the 02662 given test. --- */ 02663 extern test copy_of_equality_test_found_in_test(test t); 02664 02665 /* --- Looks through a test, returns appropriate first letter for a dummy 02666 variable to follow it. Returns '*' if none found. --- */ 02667 extern char first_letter_from_test(test t); 02668 02669 /* ------------------------ */ 02670 /* Utilities for conditions */ 02671 /* ------------------------ */ 02672 02673 /* --- Deallocates a condition list (including any NCC's and tests in it). */ 02674 extern void deallocate_condition_list(condition * cond_list); 02675 02676 /* --- Returns a new copy of the given condition. --- */ 02677 extern condition *copy_condition(condition * cond); 02678 02679 /* --- Copies the given condition list, returning pointers to the 02680 top-most and bottom-most conditions in the new copy. --- */ 02681 extern void copy_condition_list(condition * top_cond, condition ** dest_top, condition ** dest_bottom); 02682 02683 /* --- Returns TRUE iff the two conditions are identical. --- */ 02684 extern bool conditions_are_equal(condition * c1, condition * c2); 02685 02686 /* --- Returns a hash value for the given condition. --- */ 02687 extern unsigned long hash_condition(condition * cond); 02688 02689 /* ------------------------------------ */ 02690 /* Utilities for actions and RHS values */ 02691 /* ------------------------------------ */ 02692 02693 /* --- Deallocates the given rhs_value. --- */ 02694 extern void deallocate_rhs_value(rhs_value rv); 02695 02696 /* --- Returns a new copy of the given rhs_value. --- */ 02697 extern rhs_value copy_rhs_value(rhs_value rv); 02698 02699 /* --- Deallocates the given action (singly-linked) list. --- */ 02700 extern void deallocate_action_list(action * actions); 02701 02702 /* --- Looks through an rhs_value, returns appropriate first letter for a 02703 dummy variable to follow it. Returns '*' if none found. --- */ 02704 extern char first_letter_from_rhs_value(rhs_value rv); 02705 02706 /* ------------------ */ 02707 /* Utilities for nots */ 02708 /* ------------------ */ 02709 02710 /* --- Deallocates the given (singly-linked) list of Nots. --- */ 02711 extern void deallocate_list_of_nots(not * nots); 02712 02713 /* -------------------------------------------------------------------- 02714 Transitive Closure Utilities 02715 Marking, Unmarking, and Collecting Symbols 02716 02717 Get_new_tc_number() is called from lots of places. Any time we need 02718 to mark a set of identifiers and/or variables, we get a new tc_number 02719 by calling this routine, then proceed to mark various ids or vars 02720 by setting the sym->id.tc_num or sym->var.tc_num fields. 02721 02722 Sometimes in addition to marking symbols using their tc_num fields, 02723 we also want to build up a list of the symbols we've marked. So, 02724 the routines here take an "id_list" or "var_list" argument. This 02725 argument should be NIL if no such list is desired. If non-NIL, it 02726 should point to the header of the linked list being built. 02727 02728 Transitive Closure Calculations for Conditions and Actions 02729 02730 Usage: 02731 1. Set my_tc = get_new_tc_number() to start a new TC 02732 2. (optional) If you want linked lists of symbols in the TC, initialize 02733 id_list=NIL and var_list=NIL. 02734 If you're not using id_list and/or var_list, give NIL for "&id_list" 02735 and/or "&var_list" in the function calls below. 02736 3. (optional) setup any id's or var's that you want to include in the 02737 initial TC, by calling 02738 add_symbol_to_tc (sym, my_tc, &id_list, &var_list) 02739 (If not using id_list or var_list, you can just mark 02740 sym->{id,var}.tc_num = my_tc instead.) 02741 4. To do the work you want, use any of the following any number of times: 02742 add_cond_to_tc (cond, my_tc, &id_list, &var_list); 02743 add_action_to_tc (cond, my_tc, &id_list, &var_list); 02744 result = cond_is_in_tc (cond, my_tc); 02745 result = action_is_in_tc (action, my_tc); 02746 5. When finished, free the cons cells in id_list and var_list (but 02747 don't call symbol_remove_ref() on the symbols in them). 02748 02749 Warning: actions must not contain reteloc's or rhs unbound variables here. 02750 -------------------------------------------------------------------- */ 02751 02752 tc_number get_new_tc_number(void); 02753 02754 extern void add_symbol_to_tc(Symbol * sym, tc_number tc, list ** id_list, list ** var_list); 02755 extern void add_cond_to_tc(condition * c, tc_number tc, list ** id_list, list ** var_list); 02756 extern void add_action_to_tc(action * a, tc_number tc, list ** id_list, list ** var_list); 02757 extern bool cond_is_in_tc(condition * cond, tc_number tc); 02758 extern bool action_is_in_tc(action * a, tc_number tc); 02759 02760 /* -------------------------------------------------------------------- 02761 Variable Generator 02762 02763 These routines are used for generating new variables. The variables 02764 aren't necessarily "completely" new--they might occur in some existing 02765 production. But we usually need to make sure the new variables don't 02766 overlap with those already used in a *certain* production--for instance, 02767 when variablizing a chunk, we don't want to introduce a new variable that 02768 conincides with the name of a variable already in an NCC in the chunk. 02769 02770 To use these routines, first call reset_variable_generator(), giving 02771 it lists of conditions and actions whose variables should not be 02772 used. Then call generate_new_variable() any number of times; each 02773 time, you give it a string to use as the prefix for the new variable's 02774 name. The prefix string should not include the opening "<". 02775 -------------------------------------------------------------------- */ 02776 02777 extern void reset_variable_generator(condition * conds_with_vars_to_avoid, action * actions_with_vars_to_avoid); 02778 extern Symbol *generate_new_variable(char *prefix); 02779 02780 /* ------------------------------------------------------------------- 02781 Production Management 02782 02783 For each type of production, we maintain a doubly-linked list of 02784 all productions of that type. The headers of these dll's are 02785 stored in the array all_productions_of_type[]. Another array, 02786 num_productions_of_type[], keeps counts of how many productions 02787 there are of each type. 02788 02789 Production_add_ref() and production_remove_ref() are macros for 02790 incrementing and decrementing the reference count on a production. 02791 Production_remove_ref() also deallocates the production if the 02792 count goes to 0. 02793 02794 Make_production() does reordering, compile-time o-support calc's, 02795 and builds and returns a production structure for a new production. 02796 It does not enter the production into the Rete net, however. 02797 The "type" argument should be one of USER_PRODUCTION_TYPE, etc. 02798 The flag "reorder_nccs" tells whether to recursively reorder 02799 the subconditions of NCC's--this is not necessary for newly 02800 built chunks, as their NCC's are copies of other NCC's in SP's that 02801 have already been reordered. If any error occurs, make_production() 02802 returns NIL. 02803 02804 Deallocate_production() and excise_production() do just what they 02805 say. Normally deallocate_production() should be invoked only via 02806 the production_remove_ref() macro. 02807 ------------------------------------------------------------------- */ 02808 02809 #define production_add_ref(p) { (p)->reference_count++; } 02810 #define production_remove_ref(p) { \ 02811 (p)->reference_count--; \ 02812 if ((p)->reference_count == 0) \ 02813 deallocate_production(p); } 02814 02815 extern production *make_production(byte type, 02816 Symbol * name, 02817 condition ** lhs_top, condition ** lhs_bottom, action ** rhs_top, bool reorder_nccs); 02818 extern void deallocate_production(production * prod); 02819 extern void excise_production(production * prod, bool print_sharp_sign); 02820 02821 extern bool canonical_cond_greater(condition * c1, condition * c2); 02822 02823 /* ======================================================================= 02824 reorder.c 02825 BUGBUG comments here 02826 ======================================================================= */ 02827 02828 extern bool reorder_action_list(action ** action_list, tc_number lhs_tc); 02829 extern bool reorder_lhs(condition ** lhs_top, condition ** lhs_bottom, bool reorder_nccs); 02830 extern void init_reorderer(void); 02831 02832 /* ======================================================================= 02833 recmem.c 02834 02835 Init_firer() and init_chunker() should be called at startup time, to 02836 do initialization. 02837 02838 Do_preference_phase() runs the entire preference phase. This is called 02839 from the top-level control in main.c. 02840 02841 Possibly_deallocate_instantiation() checks whether an instantiation 02842 can be deallocated yet, and does so if possible. This is used whenever 02843 the (implicit) reference count on the instantiation decreases. 02844 ======================================================================= */ 02845 02846 extern void init_firer(void); 02847 extern void do_preference_phase(void); 02848 02849 /* RBD BUGBUG more comments here */ 02850 extern preference *find_clone_for_level(preference * p, goal_stack_level level); 02851 extern void fill_in_new_instantiation_stuff(instantiation * inst, bool need_to_do_support_calculations); 02852 02853 /* mvp 5-17-94 */ 02854 extern void build_prohibits_list(instantiation * inst); 02855 02856 #define possibly_deallocate_instantiation(inst) { \ 02857 if ((! (inst)->preferences_generated) && \ 02858 (! (inst)->in_ms)) \ 02859 deallocate_instantiation (inst); } 02860 02861 extern void deallocate_instantiation(instantiation * inst); 02862 02863 /* ======================================================================= 02864 backtrace.c 02865 ======================================================================= */ 02866 02867 /* RBD BUGBUG more comments here */ 02868 extern void trace_locals(goal_stack_level grounds_level); 02869 extern void trace_grounded_potentials(void); 02870 extern bool trace_ungrounded_potentials(goal_stack_level grounds_level); 02871 extern void backtrace_through_instantiation(instantiation * inst, 02872 goal_stack_level grounds_level, condition * trace_cond, int indent); 02873 02874 /* ======================================================================= 02875 chunk.c 02876 ======================================================================= */ 02877 02878 /* RBD BUGBUG more comments here */ 02879 #define CHUNK_COND_HASH_TABLE_SIZE 1024 02880 #define LOG_2_CHUNK_COND_HASH_TABLE_SIZE 10 02881 02882 typedef struct chunk_cond_struct { 02883 condition *cond; /* points to the original condition */ 02884 02885 condition *instantiated_cond; /* points to cond in chunk instantiation */ 02886 condition *variablized_cond; /* points to cond in the actual chunk */ 02887 condition *saved_prev_pointer_of_variablized_cond; /* don't ask */ 02888 02889 /* dll of all cond's in a set (i.e., a chunk_cond_set, or the grounds) */ 02890 struct chunk_cond_struct *next, *prev; 02891 02892 /* dll of cond's in this particular hash bucket for this set */ 02893 struct chunk_cond_struct *next_in_bucket, *prev_in_bucket; 02894 02895 unsigned long hash_value; /* equals hash_condition(cond) */ 02896 unsigned long compressed_hash_value; /* above, compressed to a few bits */ 02897 } chunk_cond; 02898 02899 typedef struct chunk_cond_set_struct { 02900 chunk_cond *all; /* header for dll of all chunk_cond's in the set */ 02901 chunk_cond *table[CHUNK_COND_HASH_TABLE_SIZE]; /* hash table buckets */ 02902 } chunk_cond_set; 02903 02904 extern void init_chunker(void); 02905 extern void chunk_instantiation(instantiation * inst, bool allow_variablization); 02906 extern chunk_cond *make_chunk_cond_for_condition(condition * cond); 02907 extern bool add_to_chunk_cond_set(chunk_cond_set * set, chunk_cond * new_cc); 02908 02909 /* ======================================================================= 02910 osupport.c 02911 02912 Calculate_support_for_instantiation_preferences() does run-time o-support 02913 calculations -- it fills in pref->o_supported in each pref. on the 02914 instantiation. Calculate_compile_time_o_support() does the compile-time 02915 version: it takes the LHS and RHS, and fills in the a->support field in 02916 each RHS action with either UNKNOWN_SUPPORT, O_SUPPORT, or I_SUPPORT. 02917 ======================================================================= */ 02918 02919 extern void calculate_support_for_instantiation_preferences(instantiation * inst); 02920 extern void calculate_compile_time_o_support(condition * lhs, action * rhs); 02921 02922 extern void dougs_calculate_support_for_instantiation_preferences(instantiation * inst); 02923 02924 /* ======================================================================= 02925 rete.c 02926 02927 All_wmes_in_rete is the header for a dll of all the wmes currently 02928 in the rete. (This is normally equal to all of WM, except at times 02929 when WM changes have been buffered but not yet done.) The wmes 02930 are linked via their "rete_next" and "rete_prev" fields. 02931 Num_wmes_in_rete counts how many wmes there are in the rete. 02932 02933 Init_rete() initializes the rete. It should be called at startup time. 02934 02935 Any_assertions_or_retractions_ready() returns TRUE iff there are any 02936 pending changes to the match set. This is used to test for quiescence. 02937 Get_next_assertion() retrieves a pending assertion (returning TRUE) or 02938 returns FALSE is no more are available. Get_next_retraction() is 02939 similar. 02940 02941 Add_production_to_rete() adds a given production, with a given LHS, 02942 to the rete. If "refracted_inst" is non-NIL, it should point to an 02943 initial instantiation of the production. This routine returns one 02944 of NO_REFRACTED_INST, REFRACTED_INST_MATCHED, etc. (see below). 02945 Excise_production_from_rete() removes the given production from the 02946 rete, and enqueues all its existing instantiations as pending 02947 retractions. 02948 02949 Add_wme_to_rete() and remove_wme_from_rete() inform the rete of changes 02950 to WM. 02951 02952 P_node_to_conditions_and_nots() takes a p_node and (optionally) a 02953 token/wme pair, and reconstructs the (optionally instantiated) LHS 02954 for the production. The firer uses this to build the instantiated 02955 conditions; the printer uses it to reconstruct the LHS for printing. 02956 Get_symbol_from_rete_loc() takes a token/wme pair and a location 02957 specification (levels_up/field_num), examines the match (token/wme), 02958 and returns the symbol at that location. The firer uses this for 02959 resolving references in RHS actions to variables bound on the LHS. 02960 02961 Count_rete_tokens_for_production() returns a count of the number of 02962 tokens currently in use for the given production. 02963 02964 Print_partial_match_information(), print_match_set(), and 02965 the API function soar_ecPrintReteStatistics(), 02966 do printouts for various interface routines. 02967 02968 Save_rete_net() and load_rete_net() are used for the fastsave/load 02969 commands. They save/load everything to/from the given (already open) 02970 files. They return TRUE if successful, FALSE if any error occurred. 02971 ======================================================================= */ 02972 02973 extern void init_rete(void); 02974 02975 extern bool any_assertions_or_retractions_ready(void); 02976 extern bool get_next_assertion(production ** prod, struct token_struct **tok, wme ** w); 02977 extern bool get_next_retraction(struct instantiation_struct **inst); 02978 /* REW: begin 08.20.97 */ 02979 /* Special routine for retractions in removed goals. See note in rete.c */ 02980 extern bool get_next_nil_goal_retraction(struct instantiation_struct **inst); 02981 /* REW: end 08.20.97 */ 02982 02983 #define NO_REFRACTED_INST 0 /* no refracted inst. was given */ 02984 #define REFRACTED_INST_MATCHED 1 /* there was a match for the inst. */ 02985 #define REFRACTED_INST_DID_NOT_MATCH 2 /* there was no match for it */ 02986 #define DUPLICATE_PRODUCTION 3 /* the prod. was a duplicate */ 02987 extern byte add_production_to_rete(production * p, condition * lhs_top, 02988 instantiation * refracted_inst, bool warn_on_duplicates); 02989 extern void excise_production_from_rete(production * p); 02990 02991 extern void add_wme_to_rete(wme * w); 02992 extern void remove_wme_from_rete(wme * w); 02993 02994 extern void p_node_to_conditions_and_nots(struct rete_node_struct *p_node, 02995 struct token_struct *tok, 02996 wme * w, 02997 condition ** dest_top_cond, 02998 condition ** dest_bottom_cond, not ** dest_nots, action ** dest_rhs); 02999 extern Symbol *get_symbol_from_rete_loc(unsigned short levels_up, byte field_num, struct token_struct *tok, wme * w); 03000 03001 extern unsigned long count_rete_tokens_for_production(production * prod); 03002 extern void print_partial_match_information(struct rete_node_struct *p_node, wme_trace_type wtt); 03003 extern void print_match_set(wme_trace_type wtt, ms_trace_type mst); 03004 03005 extern int get_node_count_statistic(const char *node_type_name, const char *column_name, unsigned long *result); 03006 03007 extern bool save_rete_net(FILE * dest_file); 03008 extern bool load_rete_net(FILE * source_file); 03009 03010 /* ==================================================================== 03011 rhsfun.c 03012 03013 The system maintains a list of available RHS functions. Functions 03014 can appear on the RHS of productions either as values (in make actions 03015 or as arguments to other function calls) or as stand-alone actions 03016 (e.g., "write" and "halt"). When a function is executed, its C code 03017 is called with one parameter--a (consed) list of the arguments (symbols). 03018 The C function should return either a symbol (if all goes well) or NIL 03019 (if an error occurred, or if the function is a stand-alone action). 03020 03021 All available RHS functions should be setup at system startup time via 03022 calls to add_rhs_function(). It takes as arguments the name of the 03023 function (a symbol), a pointer to the corresponding C function, the 03024 number of arguments the function expects (-1 if the function can take 03025 any number of arguments), and flags indicating whether the function can 03026 be a RHS value or a stand-alone action. 03027 03028 Lookup_rhs_function() takes a symbol and returns the corresponding 03029 rhs_function structure (or NIL if there is no such function). 03030 03031 Init_built_in_rhs_functions() should be called at system startup time 03032 to setup all the built-in functions. 03033 ==================================================================== */ 03034 03035 typedef Symbol *((*rhs_function_routine) (list * args)); 03036 03037 typedef struct rhs_function_struct { 03038 struct rhs_function_struct *next; 03039 Symbol *name; 03040 rhs_function_routine f; 03041 int num_args_expected; /* -1 means it can take any number of args */ 03042 bool can_be_rhs_value; 03043 bool can_be_stand_alone_action; 03044 } rhs_function; 03045 03046 extern void add_rhs_function(Symbol * name, 03047 rhs_function_routine f, 03048 int num_args_expected, bool can_be_rhs_value, bool can_be_stand_alone_action); 03049 extern rhs_function *lookup_rhs_function(Symbol * name); 03050 extern void init_built_in_rhs_functions(void); 03051 03052 /* ====================================================================== 03053 trace.c 03054 03055 Object and stack trace formats are managed by this module. 03056 03057 Init_tracing() initializes the tables; at this point, there are no trace 03058 formats for anything. This routine should be called at startup time. 03059 03060 Trace formats are changed by calls to add_trace_format() and 03061 remove_trace_format(). Add_trace_format() returns TRUE if the 03062 format was successfully added, or FALSE if the format string didn't 03063 parse right. Remove_trace_format() returns TRUE if a trace format 03064 was actually removed, or FALSE if there was no such trace format for 03065 the given type/name restrictions. These routines take a "stack_trace" 03066 argument, which should be TRUE if the stack trace format is intended, 03067 or FALSE if the object trace format is intended. Their 03068 "type_restriction" argument should be one of FOR_ANYTHING_TF, ..., 03069 FOR_OPERATORS_TF. The "name_restriction" argument should be either 03070 a pointer to a symbol, if the trace format is restricted to apply 03071 to objects with that name, or NIL if the format can apply to any object. 03072 03073 Print_all_trace_formats() prints out either all existing stack trace 03074 or object trace formats. 03075 03076 Print_object_trace() takes an object (any symbol). It prints the 03077 trace for that object. Print_stack_trace() takes a (context) 03078 object (the state or op), the current state, the "slot_type" 03079 (one of FOR_OPERATORS_TF, etc.), and a flag indicating whether to 03080 allow %dc and %ec escapes (this flag should normally be TRUE for 03081 watch 0 traces but FALSE during a "print -stack" command). It prints 03082 the stack trace for that context object. 03083 ====================================================================== */ 03084 03085 /* trace format type restrictions */ 03086 #define FOR_ANYTHING_TF 0 /* format applies to any object */ 03087 #define FOR_STATES_TF 1 /* format applies only to states */ 03088 #define FOR_OPERATORS_TF 2 /* format applies only to operators */ 03089 03090 extern void init_tracing(void); 03091 extern bool add_trace_format(bool stack_trace, int type_restriction, 03092 Symbol * name_restriction, const char *format_string); 03093 extern bool remove_trace_format(bool stack_trace, int type_restriction, Symbol * name_restriction); 03094 extern void print_all_trace_formats(bool stack_trace); 03095 03096 extern void print_object_trace(Symbol * object); 03097 extern void print_stack_trace(Symbol * object, Symbol * state, int slot_type, bool allow_cycle_counts); 03098 03099 extern char *help_on_trace_format_escapes[]; 03100 03101 /* ======================================================================= 03102 io.c 03103 03104 General Soar I/O System Routines 03105 03106 User-defined Soar I/O routines should be added at system startup time 03107 via calls to add_input_function() and add_output_function(). These 03108 calls add things to the system's list of (1) functions to be called 03109 every input cycle, and (2) symbol-to-function mappings for output 03110 commands. File io.c contains the system I/O mechanism itself (i.e., 03111 the stuff that calls the input and output functions), plus the text 03112 I/O routines. 03113 03114 Init_soar_io() does what it say. Do_input_cycle() and do_output_cycle() 03115 perform the entire input and output cycles -- these routines are called 03116 once per elaboration cycle. (once per Decision cycle in Soar 8). 03117 The output module is notified about WM changes via a call to 03118 inform_output_module_of_wm_changes(). 03119 ======================================================================= */ 03120 03121 extern void init_soar_io(void); 03122 extern void do_input_cycle(void); 03123 extern void do_output_cycle(void); 03124 03125 extern void inform_output_module_of_wm_changes(list * wmes_being_added, list * wmes_being_removed); 03126 03127 /* ======================================================================= 03128 callback.c 03129 03130 Callback.c contains a callback facility enabling users to add their 03131 own code to handle certain events occurring in the Soar architecture. 03132 For more details, see the descriptions of the individual callbacks, 03133 in callback.h. 03134 ======================================================================= */ 03135 03136 #include "callback.h" 03137 03138 extern unsigned long soar_global_callback_error; 03139 03140 /* ======================================================================= 03141 Input Functions 03142 03143 Input functions take one parameter--a mode (integer) indicating why the 03144 function is being called. The mode is either TOP_STATE_JUST_CREATED, 03145 NORMAL_INPUT_CYCLE, or TOP_STATE_JUST_REMOVED. In the input cycle 03146 immediately following the installation of the top state, each input 03147 function is called once with TOP_STATE_JUST_CREATED and then once with 03148 NORMAL_INPUT_CYCLE. In the input cycle immediately following the removal 03149 of the top state, the functions are called with TOP_STATE_JUST_REMOVED. 03150 If the top state is *replaced*, the functions are called with 03151 TOP_STATE_JUST_REMOVED, then TOP_STATE_JUST_CREATED, and then 03152 NORMAL_INPUT_CYCLE. 03153 03154 Input routines create, modify, and delete input structures via calls 03155 to add_input_wme() and remove_input_wme(). The arguments to add_input_wme() 03156 indicate the id/attr/value components of the wme to be added. Each of 03157 these components must be either (1) the current value of the global 03158 variable "top_state", or (2) the returned value from a call to 03159 get_new_io_identifier(), get_io_sym_constant(), get_io_int_constant(), 03160 or get_io_float_constant(). [The idea behind creating the components this 03161 way is to avoid having I/O functions deal with the reference counts on 03162 symbols.] For every call an I/O function makes to get_xxx(), it should 03163 later call release_io_symbol(). Release_io_symbol() should *not* be 03164 called with the value of "top_state"--*only* the components obtained via 03165 get_xxx(). 03166 03167 The add_input_wme() routine returns a pointer to the wme added. The input 03168 routine shouldn't use this pointer in any way except to save it around for 03169 a later call to remove_input_wme(). Example: 03170 03171 float current_sensor_value; 03172 wme *w; 03173 Symbol *s1,*s2; 03174 ... insert code to read value into current_sensor_value here ... 03175 s1 = get_io_sym_constant ("sensor-value"); 03176 s2 = get_io_float_constant (current_sensor_value); 03177 ... add to working memory (S1 ^sensor-value 37.5) ... 03178 w = add_input_wme (top_state, s1, s2); 03179 release_io_symbol (s1); 03180 release_io_symbol (s2); 03181 03182 On some later call, the input function might call remove_input_wme (w) 03183 to remove (S1 ^sensor-value 37.5) from working memory. 03184 03185 To remove an entire input structure, it is sufficient for the input 03186 function to call remove_input_wme() on just the top link wme. The input 03187 function need not call remove_input_wme() on each and every wme in the 03188 structure. (Soar automagically garbage collects all the wmes in the 03189 now-disconnected structure.) Note that when an input function is called 03190 with TOP_STATE_JUST_REMOVED, all existing input structures have already 03191 been garbage collected (since the top state no longer exists), so the 03192 input function should never call remove_input_wme() when mode is 03193 TOP_STATE_JUST_REMOVED. Remove_input_wme() normally returns TRUE, 03194 indicating success. It returns FALSE if an error occurs (e.g., if the 03195 wme argument isn't in WM). 03196 ======================================================================= */ 03197 03198 #define TOP_STATE_JUST_CREATED 1 03199 #define NORMAL_INPUT_CYCLE 2 03200 #define TOP_STATE_JUST_REMOVED 3 03201 03202 extern Symbol *get_new_io_identifier(char first_letter); 03203 extern Symbol *get_io_sym_constant(char *name); 03204 extern Symbol *get_io_int_constant(long value); 03205 extern Symbol *get_io_float_constant(float value); 03206 extern void release_io_symbol(Symbol * sym); 03207 03208 extern wme *add_input_wme(Symbol * id, Symbol * attr, Symbol * value); 03209 extern bool remove_input_wme(wme * w); 03210 03211 /* ======================================================================= 03212 Output Functions 03213 03214 Output functions take two parameters--a mode (integer) indicating why the 03215 function is being called, and a pointer to a chain of io_wme structures. 03216 The mode is either ADDED_OUTPUT_COMMAND (used when an output link is first 03217 created), MODIFIED_OUTPUT_COMMAND (used when the transitive closure of an 03218 existing link changes), or REMOVED_OUTPUT_COMMAND (used when the output 03219 link is removed from working memory). 03220 03221 The chain of io_wme structures is connected via the "next" fields in the 03222 structures; for the last io_wme, next==NIL. When mode is either 03223 ADDED_OUTPUT_COMMAND or MODIFIED_OUTPUT_COMMAND, this chain contains 03224 all the wmes in the current transitive closure of the output link 03225 (including the output link wme itself). When mode is 03226 REMOVED_OUTPUT_COMMAND, the chain consists of just one io_wme--the top-level 03227 ouput link being removed. 03228 03229 Output functions should inspect the io_wme chain and take whatever 03230 actions are appropriate. Note that Soar deallocates the io_wme chain 03231 after calling the output function, so the output function is responsible 03232 for saving any necessary information around for later. 03233 03234 How can an output function examine the io_wme's? The io_wme structures 03235 indicate the id/attr/value of the wmes in the output structure. See 03236 the comments above for symtab.c for an explanation of the structure 03237 of these symbols. 03238 03239 Get_output_value() is a simple utility routine for finding things in 03240 an io_wme chain. It takes "outputs" (the io_wme chain), and "id" and 03241 "attr" (symbols to match against the wmes), and returns the value from 03242 the first wme in the chain with a matching id and attribute. Either 03243 "id" or "attr" (or both) can be specified as "don't care" by giving 03244 NULL (0) pointers for them instead of pointers to symbols. If no matching 03245 wme is found, the function returns a NULL pointer. 03246 ======================================================================= */ 03247 03248 typedef struct io_wme_struct { 03249 /* 03250 * 12.08.00 Put next field last, so id,attr,value fall in same position 03251 * as in a wme structure 03252 */ 03253 Symbol *id; /* id, attribute, and value of the wme */ 03254 Symbol *attr; 03255 Symbol *value; 03256 struct io_wme_struct *next; /* points to next io_wme in the chain */ 03257 } io_wme; 03258 03259 enum captured_action_type { 03260 ADD_WME, 03261 REMOVE_WME 03262 }; 03263 03264 typedef struct captured_action_struct { 03265 03266 struct captured_action_struct *next; 03267 int dc; 03268 enum captured_action_type action; 03269 03270 void *args; 03271 03272 } captured_action; 03273 03274 #define ADDED_OUTPUT_COMMAND 1 03275 #define MODIFIED_OUTPUT_COMMAND 2 03276 #define REMOVED_OUTPUT_COMMAND 3 03277 03278 typedef struct output_call_info_struct { 03279 int mode; 03280 io_wme *outputs; 03281 } output_call_info; 03282 03283 extern Symbol *get_output_value(io_wme * outputs, Symbol * id, Symbol * attr); 03284 03285 /* =========================================================================== 03286 Miscellaneous functions that I needed to declare because I used them in 03287 more than one file, even though they're not really part of a "module 03288 interface" or something like that. 03289 =========================================================================== */ 03290 03291 extern Symbol *get_next_io_symbol_from_text_input_line(char **text_read_position); /* in io.c */ 03292 03293 /* -------------------------------------------------------------------- */ 03294 /* */ 03295 /* Macros for handling multi-agent switching in Soar. */ 03296 03297 /* RBD BUGBUG more comments here, or should this stuff be here at all? */ 03298 03299 #define UPDATE_LINKS_NORMALLY 0 03300 #define UPDATE_DISCONNECTED_IDS_LIST 1 03301 #define JUST_UPDATE_COUNT 2 03302 03303 /* AGR 564 begins */ 03304 /* ====================================================================== 03305 explain.c 03306 ====================================================================== */ 03307 03308 /* 03309 For each production which is backtraced through, keep the name of the 03310 production, which condition was being traced (from the RHS of this 03311 production firing) and then the lists of grounds, potentials, locals 03312 and negateds generated during the backtrace. 03313 At the moment I'm not guaranteeing that each condition appears in the 03314 correct list -- this is because elements move between lists after their 03315 initial positioning. 03316 */ 03317 03318 #define PROD_NAME_SIZE 256 03319 typedef struct backtrace_struct { 03320 int result; /* 1 when this is a result of the chunk */ 03321 condition *trace_cond; /* The (local) condition being traced */ 03322 char prod_name[PROD_NAME_SIZE]; /* The production's name */ 03323 condition *grounds; /* The list of conds for the LHS of chunk */ 03324 condition *potentials; /* The list of conds which aren't linked */ 03325 condition *locals; /* Conds in the subgoal -- need to BT */ 03326 condition *negated; /* Negated conditions (sub/super) */ 03327 struct backtrace_struct *next_backtrace; /* Pointer to next in this list */ 03328 } backtrace_str; 03329 03330 /* 03331 For each chunk (or justification) take a copy of its conds and actions, 03332 and the list of productions which were backtraced through in creating it. 03333 Also keep a list of all of the grounds (WMEs in the supergoal) which were 03334 tested as the chunk was formed. 03335 */ 03336 03337 typedef struct explain_chunk_struct { 03338 char name[PROD_NAME_SIZE]; /* Name of this chunk/justification */ 03339 condition *conds; /* Variablized list of conditions */ 03340 action *actions; /* Variablized list of actions */ 03341 struct backtrace_struct *backtrace; /* List of back traced productions */ 03342 struct explain_chunk_struct *next_chunk; /* Next chunk in the list */ 03343 condition *all_grounds; /* All conditions which go to LHS -- 03344 must be in same order as the chunk's 03345 conditions. */ 03346 } explain_chunk_str; 03347 /* AGR 564 ends */ 03348 03349 /* RBD added decl's of these routines because they were called from files 03350 other than explain.c. I don't know what they do. */ 03351 extern void explain_add_temp_to_backtrace_list(backtrace_str * temp, 03352 cons * grounds, cons * pots, cons * locals, cons * negateds); 03353 extern void explain_add_temp_to_chunk_list(explain_chunk_str * temp); 03354 extern void reset_backtrace_list(void); 03355 extern void reset_explain(void); 03356 extern void init_explain(void); 03357 extern void explain_full_trace(void); 03358 extern void explain_chunk(char *chunk_name, int cond_number); 03359 extern void explain_list_chunks(void); 03360 extern explain_chunk_str *find_chunk(explain_chunk_str * chunk, char *name); 03361 extern void explain_trace_chunk(explain_chunk_str * chunk); 03362 extern condition *find_ground(explain_chunk_str * chunk, int number); 03363 extern void explain_trace(char *chunk_name, backtrace_str * prod_list, condition * ground); 03364 03365 /* REW: begin 08.20.97 */ 03366 03367 /* Export ms_change structure to entire code in order to include pointers to 03368 assertion and retractions lists directly on goals. */ 03369 03370 /* BUGBUG ms changes only really need tok (the tok from the p-node), 03371 not a tok+wme pair. Need to change the firer for this though. */ 03372 03373 /* --- info about a change to the match set --- */ 03374 typedef struct ms_change_struct { 03375 struct ms_change_struct *next; /* dll for all p nodes */ 03376 struct ms_change_struct *prev; 03377 struct ms_change_struct *next_of_node; /* dll for just this p node */ 03378 struct ms_change_struct *prev_of_node; 03379 struct rete_node_struct *p_node; /* for retractions, this can be NIL 03380 if the p_node has been excised */ 03381 struct token_struct *tok; /* for assertions only */ 03382 03383 wme *w; /* for assertions only */ 03384 struct instantiation_struct *inst; /* for retractions only */ 03385 /* REW: begin 08.20.97 */ 03386 Symbol *goal; 03387 goal_stack_level level; /* Level of the match of the assertion or retraction */ 03388 struct ms_change_struct *next_in_level; /* dll for goal level */ 03389 struct ms_change_struct *prev_in_level; 03390 /* REW: end 08.20.97 */ 03391 } ms_change; 03392 /* REW: end 08.20.97 */ 03393 03394 /* !!!!!!!!!!!!!!!! here's the agent structure !!!!!!!!!!!!!!!!!!!!!!!!*/ 03395 /*----------------------------------------------------------------------*/ 03396 /* */ 03397 /* Agent structure used to hold what were previously global variables */ 03398 /* in the single-agent Soar. */ 03399 /* */ 03400 /*----------------------------------------------------------------------*/ 03401 03402 /* WARNING!! If you add a new global into the Soar C code, be 03403 sure to use the current_agent macro to ensure compatibility 03404 with the multi-agent code! E.g. if your new global is "foo" 03405 then do NOT refer to it in the code as "foo" but instead as 03406 "current_agent(foo)". */ 03407 03408 /* If you define a new global, initialize it in the create_soar_agent 03409 routine. AGR 527c 3-May-94 */ 03410 03411 typedef struct agent_struct { 03412 03413 /* ----------------------- Rete stuff -------------------------- */ 03414 03415 /* Hash tables for alpha memories, and for entries in left & right memories */ 03416 void *left_ht; 03417 void *right_ht; 03418 hash_table *(alpha_hash_tables[16]); 03419 03420 /* Number of WMEs, and list of WMEs, the Rete has been told about */ 03421 unsigned long num_wmes_in_rete; 03422 wme *all_wmes_in_rete; 03423 03424 /* Memory pools */ 03425 memory_pool rete_node_pool; 03426 memory_pool rete_test_pool; 03427 memory_pool right_mem_pool; 03428 memory_pool token_pool; 03429 memory_pool alpha_mem_pool; 03430 memory_pool ms_change_pool; 03431 memory_pool node_varnames_pool; 03432 03433 /* Dummy nodes and tokens */ 03434 struct rete_node_struct *dummy_top_node; 03435 struct token_struct *dummy_top_token; 03436 03437 /* Various Rete statistics counters */ 03438 unsigned long rete_node_counts[256]; 03439 unsigned long rete_node_counts_if_no_sharing[256]; 03440 unsigned long token_additions; 03441 unsigned long token_additions_without_sharing; 03442 unsigned long num_right_activations; 03443 unsigned long num_left_activations; 03444 unsigned long num_null_right_activations; 03445 unsigned long num_null_left_activations; 03446 03447 /* Miscellaneous other stuff */ 03448 unsigned long alpha_mem_id_counter; /* node id's for hashing */ 03449 unsigned long beta_node_id_counter; 03450 struct ms_change_struct *ms_assertions; /* changes to match set */ 03451 struct ms_change_struct *ms_retractions; 03452 03453 /* ----------------------- Lexer stuff -------------------------- */ 03454 03455 lexer_source_file *current_file; /* file we're currently reading */ 03456 char current_char; /* holds current input character */ 03457 struct lexeme_info lexeme; /* holds current lexeme */ 03458 bool print_prompt_flag; 03459 03460 /* ---------------- Predefined Symbols ------------------------- 03461 Certain symbols are used so frequently that we create them at 03462 system startup time and never deallocate them. 03463 ------------------------------------------------------------- */ 03464 03465 Symbol *attribute_symbol; 03466 Symbol *choices_symbol; 03467 Symbol *conflict_symbol; 03468 Symbol *constraint_failure_symbol; 03469 Symbol *goal_symbol; 03470 Symbol *impasse_symbol; 03471 Symbol *io_symbol; 03472 Symbol *item_symbol; 03473 Symbol *multiple_symbol; 03474 Symbol *name_symbol; 03475 Symbol *nil_symbol; 03476 Symbol *no_change_symbol; 03477 Symbol *none_symbol; 03478 Symbol *o_context_variable; 03479 Symbol *object_symbol; 03480 Symbol *operator_symbol; 03481 Symbol *problem_space_symbol; 03482 Symbol *quiescence_symbol; 03483 Symbol *s_context_variable; 03484 Symbol *so_context_variable; 03485 Symbol *ss_context_variable; 03486 Symbol *sso_context_variable; 03487 Symbol *sss_context_variable; 03488 Symbol *state_symbol; 03489 Symbol *superstate_symbol; 03490 Symbol *t_symbol; 03491 Symbol *tie_symbol; 03492 Symbol *to_context_variable; 03493 Symbol *ts_context_variable; 03494 Symbol *type_symbol; 03495 Symbol *wait_symbol; /* REW: 10.24.97 */ 03496 03497 /* ----------------------- Symbol table stuff -------------------------- */ 03498 03499 unsigned long current_symbol_hash_id; 03500 unsigned long id_counter[26]; 03501 03502 struct hash_table_struct *float_constant_hash_table; 03503 struct hash_table_struct *identifier_hash_table; 03504 struct hash_table_struct *int_constant_hash_table; 03505 struct hash_table_struct *sym_constant_hash_table; 03506 struct hash_table_struct *variable_hash_table; 03507 03508 memory_pool float_constant_pool; 03509 memory_pool identifier_pool; 03510 memory_pool int_constant_pool; 03511 memory_pool sym_constant_pool; 03512 memory_pool variable_pool; 03513 03514 /* ----------------------- Top-level stuff -------------------------- */ 03515 03516 /* --- headers of dll's of all productions of each type --- */ 03517 production *all_productions_of_type[NUM_PRODUCTION_TYPES]; 03518 /* --- counts of how many productions there are of each type --- */ 03519 unsigned long num_productions_of_type[NUM_PRODUCTION_TYPES]; 03520 03521 /* --- lists of symbols (PS names) declared chunk-free and chunky --- */ 03522 list *chunk_free_problem_spaces; 03523 list *chunky_problem_spaces; /* AGR MVL1 */ 03524 03525 /* --- default depth for "print" command --- */ 03526 int default_wme_depth; /* AGR 646 */ 03527 03528 /* --- stuff for "input-period" command --- */ 03529 /* --- in Soar8, input runs once at beginning of D cycle, no matter what */ 03530 int input_period; /* AGR REW1 */ 03531 bool input_cycle_flag; /* AGR REW1 */ 03532 03533 /* --- current top level phase --- */ 03534 enum top_level_phase current_phase; 03535 03536 /* --- to interrupt at the end of the current phase, set stop_soar to TRUE 03537 and reason_for_stopping to some appropriate string --- */ 03538 byte stop_soar; 03539 const char *reason_for_stopping; 03540 03541 /* --- the RHS action (halt) sets this TRUE --- */ 03542 bool system_halted; 03543 03544 /* --- stuff for max-chunks (which is a sysparam) --- */ 03545 unsigned long chunks_this_d_cycle; /* # chunks built this DC */ 03546 bool max_chunks_reached; 03547 03548 /* --- list of productions whose firings are being traced --- */ 03549 list *productions_being_traced; 03550 03551 /* --- various user-settable system parameters --- */ 03552 long sysparams[HIGHEST_SYSPARAM_NUMBER + 1]; 03553 03554 /* --- parameters for running Soar --- */ 03555 /* --- the code loops go_number times over the go_type phases --- */ 03556 long go_number; /* How many times to "go" */ 03557 Symbol *go_slot_attr; /* The context slot checked */ 03558 goal_stack_level go_slot_level; /* The goal stack level checked */ 03559 enum go_type_enum go_type; /* The phase type used */ 03560 03561 /* --- Top-level Statistics --- */ 03562 03563 /* running total of WM sizes at end of phases */ 03564 double cumulative_wm_size; 03565 /* number of items included in "cumulative_wm_size" sum */ 03566 unsigned long num_wm_sizes_accumulated; 03567 03568 unsigned long max_wm_size; /* maximum size of WM so far */ 03569 unsigned long wme_addition_count; /* # of wmes added to WM */ 03570 unsigned long wme_removal_count; /* # of wmes removed from WM */ 03571 unsigned long d_cycle_count; /* # of DC's run so far */ 03572 unsigned long e_cycle_count; /* # of EC's run so far */ 03573 /* in Soar 8, e_cycles_this_d_cycle is reset to zero for every 03574 propose and apply phase */ 03575 unsigned long e_cycles_this_d_cycle; /* # of EC's run this DC */ 03576 unsigned long num_existing_wmes; /* current WM size */ 03577 unsigned long production_firing_count; /* # of prod. firings */ 03578 03579 /* REW: begin 09.15.96 */ 03580 /* in Soar 8, PE's are done only during the APPLY phase */ 03581 unsigned long pe_cycle_count; /* # of PE's run so far */ 03582 unsigned long pe_cycles_this_d_cycle; /* # of PE's run this DC */ 03583 03584 parent_inst *parent_list_head; 03585 /* REW: end 09.15.96 */ 03586 03587 /* ----------------------- Timing statistics -------------------------- */ 03588 03589 /* 03590 For Soar 7, the timing code has been completely revamped. When the compile 03591 flag NO_TIMING_STUFF is not set, statistics will be now be collected on the 03592 total cpu time, total kernel time, time spent in the individual phases of a 03593 decision cycle, time spent executing the input and output functions, and time 03594 spent executing callbacks (or monitors). When the DETAILED_TIMING_STATS flag 03595 is set, additional statistics will be collected for ownership, match, and 03596 chunking computations according to the phase in which they occur. (Notice 03597 that DETAILED_TIMING_STATS can only be collected when NO_TIMING_STUFF is not 03598 true.) 03599 03600 The total_cpu_time is turned on when one of the run_<x> functions is 03601 initiated. This timer is not turned off while the do_one_top_level_phase() 03602 function is executing. The total_kernel_time timer is turned on just after 03603 the total_cpu_time timer and turned off just before the other is turned off. 03604 This guarantees that the total kernel time -- including the time it takes to 03605 turn on and off the kernel timer -- is a part of the total cpu time. The 03606 total_kernel_time is also turned off whenever a callback is initiated or when 03607 the input and output functions are executing. 03608 03609 The decision_cycle_phase_timers measure the kernel time for each phase of the 03610 decision cycle (ie, INPUT_PHASE, PREFERENCE_PHASE, WM_PHASE, OUTPUT_PHASE, 03611 and DECISION_PHASE). Each is turned on at the beginning of its corresponding 03612 phase in do_one_top_level_phase and turned off at the end of that phase. 03613 These timers are also turned off for callbacks and during the execution of 03614 the input and output functions. 03615 03616 The monitors_cpu_time timers are also indexed by the current phase. Whenever 03617 a callback is initiated, both the total_kernel_time and 03618 decision_cycle_phase_timer for the current phase are turned off and the 03619 monitors_cpu_time turned on. After the callback has terminated, the kernel 03620 timers are turned back on. Notice that the same relationship holds here as 03621 it did between the total_cpu_time and total_kernel_time timers. The 03622 total_kernel_time is always turned off last and turned on first, in 03623 comparison to the decision_cycle_phase_timer. This means that turning the 03624 decision_cycle_phase_timers on and off is included as part of the kernel time 03625 and helps ensure that the total_kernel_time is always greater than the sum of 03626 the decision_cycle_timers. 03627 03628 The input_function_cpu_time and output_function_cpu_time timers measure the 03629 time it takes to execute the input and output functions respectively. Both 03630 the total_kernel_time and decision_cycle_phase_timers are turned off when 03631 these timers are turned on (with the same ordering as discussed previously). 03632 The input function is a little tricky. Because add-wme can be called by the 03633 input routine, which then calls do_buffered_wm_and_ownership_changes, we 03634 can't just turn off the kernel timers for input and expect to get numbers for 03635 both match_time (see next para) and kernel time. The solution implemented in 03636 the 28.07.96 changes is to not turn off the kernel timers until the actual 03637 INPUT_PHASE_CALLBACK is initiated. This takes care of all but direct 03638 additions and removals of WMEs. Since these are done through the add-wme and 03639 remove-wme commands, the input_timer is turned off there was well, and the 03640 kernel timers turned back on (for the buffered wm changes). However, this is 03641 a hack and may introduce problems when add-wme and remove-wme are used at the 03642 command line or someplace in the decision cycle other than input (probably 03643 rare but possible). 03644 03645 The DETAILED_TIMING_STATS flag enables collection of statistics on match, 03646 ownership and chunking calculations performed in each part of the decision 03647 cycle. An 'other' value is reported which is simply the difference between 03648 the sum of the deailed timers and the kernel timer for some pahse. The other 03649 value should always be greater than or equal to zero. 03650 03651 The "stats" command (in soarCommandUtils) has been updated to report these 03652 new timing values. The output is provided in a spreadsheet-style format to 03653 display the information in a succinct form. There are also some derived 03654 totals in that report. The derived totals in the right column are simply the 03655 sum of the all the other columns in a particular row; for example, the 03656 derived total for the first row, kernel time, is just the sum of all the 03657 decision_cycle_phase_timers. The derived totals in the bottom row are the 03658 sum of all the basic timers in that row (i.e., no DETAILED statistics are 03659 included in the sum). For example, the derived total under input is equal to 03660 the sum of decision_cycle_phase_timer and the monitors_time for the 03661 INPUT_PHASE, and the input_function_cpu_time and represents the total time 03662 spent in the input phase for the current run. The number in the lower 03663 right-hand corner is the sum of the derived totals above it in that right 03664 column (and should always be equal to the numbers to the left of it in that 03665 row). 03666 03667 Also reported with the stats command are the values of total_cpu_time and 03668 total_kernel_time. If the ordering discussed above is strictly enforced, 03669 total_kernel_time should always be slightly greater than the derived total 03670 kernel time and total_cpu_time greater than the derived total CPU time. REW */ 03671 03672 /* REW: begin 28.07.96 */ 03673 #ifndef NO_TIMING_STUFF 03674 03675 TIMER_VALUE start_total_tv; 03676 TIMER_VALUE total_cpu_time; 03677 TIMER_VALUE start_kernel_tv, start_phase_tv; 03678 TIMER_VALUE total_kernel_time; 03679 03680 TIMER_VALUE decision_cycle_phase_timers[6]; 03681 TIMER_VALUE monitors_cpu_time[6]; 03682 TIMER_VALUE input_function_cpu_time; 03683 TIMER_VALUE output_function_cpu_time; 03684 /* REW: end 28.07.96 */ 03685 03686 /* REW: begin 28.07.96 */ 03687 /* accumulated cpu time spent in various parts of the system */ 03688 #ifdef DETAILED_TIMING_STATS 03689 TIMER_VALUE ownership_cpu_time[6]; 03690 TIMER_VALUE chunking_cpu_time[6]; 03691 TIMER_VALUE match_cpu_time[6]; 03692 /* REW: begin 11.25.96 */ 03693 TIMER_VALUE start_gds_tv, total_gds_time; 03694 TIMER_VALUE gds_cpu_time[6]; 03695 /* REW: end 11.25.96 */ 03696 /* REW: end 28.07.96 */ 03697 #endif 03698 03699 #ifdef DC_HISTOGRAM 03700 TIMER_VALUE *dc_histogram_tv; 03701 int dc_histogram_sz; 03702 int dc_histogram_offset; 03703 TIMER_VALUE start_dc_tv; 03704 int dc_histogram_freq; 03705 bool dc_histogram_now; 03706 #endif /* DC_HISTOGRAM */ 03707 03708 #ifdef KT_HISTOGRAM 03709 TIMER_VALUE *kt_histogram_tv; 03710 int kt_histogram_sz; 03711 int kt_histogram_offset; 03712 #endif 03713 03714 #endif /* !NO_TIMING_STUFF */ 03715 03716 #ifdef REAL_TIME_BEHAVIOR 03717 /* RMJ */ 03718 /* Keep track of real time steps for constant real-time per decision */ 03719 TIMER_VALUE *real_time_tracker; 03720 bool real_time_idling; 03721 #endif 03722 03723 #ifdef ATTENTION_LAPSE 03724 /* RMJ */ 03725 /* Keep track of duration of attentional lapses */ 03726 TIMER_VALUE *attention_lapse_tracker; 03727 bool attention_lapsing; 03728 #endif 03729 03730 /* ----------------------- Chunker stuff -------------------------- */ 03731 03732 tc_number backtrace_number; 03733 memory_pool chunk_cond_pool; 03734 unsigned long chunk_count; 03735 unsigned long justification_count; 03736 bool chunk_free_flag; 03737 bool chunky_flag; /* AGR MVL1 */ 03738 list *grounds; 03739 tc_number grounds_tc; 03740 list *instantiations_with_nots; 03741 list *locals; 03742 tc_number locals_tc; 03743 list *positive_potentials; 03744 tc_number potentials_tc; 03745 chunk_cond_set negated_set; 03746 preference *results; 03747 goal_stack_level results_match_goal_level; 03748 tc_number results_tc_number; 03749 tc_number variablization_tc; 03750 bool variablize_this_chunk; 03751 preference *extra_result_prefs_from_instantiation; 03752 bool quiescence_t_flag; 03753 char chunk_name_prefix[kChunkNamePrefixMaxLength]; /* kjh (B14) */ 03754 03755 /* ----------------------- Misc. top-level stuff -------------------------- */ 03756 03757 memory_pool action_pool; 03758 memory_pool complex_test_pool; 03759 memory_pool condition_pool; 03760 memory_pool not_pool; 03761 memory_pool production_pool; 03762 03763 /* ----------------------- Reorderer stuff -------------------------- */ 03764 03765 memory_pool saved_test_pool; 03766 03767 /* ----------------------- Memory utilities -------------------------- */ 03768 03769 /* Counters for memory usage of various types */ 03770 unsigned long memory_for_usage[NUM_MEM_USAGE_CODES]; 03771 03772 /* List of all memory pools being used */ 03773 memory_pool *memory_pools_in_use; 03774 03775 memory_pool cons_cell_pool; /* pool for cons cells */ 03776 memory_pool dl_cons_pool; /* doubly-linked list cells */ 03777 03778 /* ----------------------- Explain.c stuff -------------------------- */ 03779 03780 backtrace_str *explain_backtrace_list; /* AGR 564 */ 03781 explain_chunk_str *explain_chunk_list; /* AGR 564 */ 03782 char explain_chunk_name[256]; /* AGR 564 */ 03783 /* made explain_flag EXPLAIN_SYSPARAM instead, KJC 7/96 */ 03784 /* bool explain_flag; */ 03785 03786 /* ----------------------- Firer stuff -------------------------- */ 03787 03788 memory_pool instantiation_pool; 03789 instantiation *newly_created_instantiations; 03790 03791 /* production_being_fired -- during firing, points to the prod. being fired */ 03792 production *production_being_fired; 03793 03794 unsigned long max_rhs_unbound_variables; 03795 Symbol **rhs_variable_bindings; 03796 03797 /* ================================================================== 03798 Decider stuff 03799 =================================================================== */ 03800 03801 memory_pool preference_pool; 03802 03803 unsigned long current_wme_timetag; 03804 memory_pool wme_pool; 03805 list *wmes_to_add; 03806 list *wmes_to_remove; 03807 03808 /* --------------------------------------------------------------------- 03809 Top_goal and bottom_goal point to the top and bottom goal identifiers, 03810 respectively. (If there is no goal stack at all, they're both NIL.) 03811 Top_state points to the top state (symbol) if there is a top state, and 03812 is NIL of there isn't any top state selected. 03813 --------------------------------------------------------------------- */ 03814 03815 Symbol *bottom_goal; 03816 Symbol *top_goal; 03817 Symbol *top_state; 03818 03819 Symbol *highest_goal_whose_context_changed; 03820 dl_list *changed_slots; 03821 dl_list *context_slots_with_changed_acceptable_preferences; 03822 memory_pool slot_pool; 03823 list *slots_for_possible_removal; 03824 03825 dl_list *disconnected_ids; 03826 goal_stack_level highest_level_anything_could_fall_from; 03827 dl_list *ids_with_unknown_level; 03828 goal_stack_level lowest_level_anything_could_fall_to; 03829 tc_number mark_tc_number; 03830 goal_stack_level level_at_which_marking_started; 03831 goal_stack_level walk_level; 03832 tc_number walk_tc_number; 03833 list *promoted_ids; 03834 int link_update_mode; 03835 03836 /* ------------------ Printing utilities stuff --------------------- */ 03837 03838 #define PRINTED_OUTPUT_STRING_SIZE MAX_LEXEME_LENGTH*2+10 03839 FILE *log_file; 03840 char *log_file_name; 03841 bool logging_to_file; 03842 char printed_output_string[PRINTED_OUTPUT_STRING_SIZE]; 03843 int printer_output_column; 03844 bool redirecting_to_file; 03845 FILE *redirection_file; 03846 int saved_printer_output_column; 03847 03848 /* kjh(CUSP-B10) begin */ 03849 /* ------------------ Recording/replaying stuff --------------------- */ 03850 /* bool replaying; */ 03851 /* kjh(CUSP-B10) end */ 03852 03853 #ifdef USE_CAPTURE_REPLAY 03854 FILE *capture_fileID; 03855 FILE *replay_fileID; 03856 unsigned long *replay_timetags; 03857 captured_action **replay_actions; 03858 unsigned long dc_to_replay; 03859 bool timetag_mismatch; 03860 #endif 03861 03862 /* ----------------------- Trace Formats -------------------------- */ 03863 03864 struct trace_format_struct *(object_tf_for_anything[3]); 03865 struct hash_table_struct *(object_tr_ht[3]); 03866 bool printing_stack_traces; 03867 struct trace_format_struct *(stack_tf_for_anything[3]); 03868 struct hash_table_struct *(stack_tr_ht[3]); 03869 tc_number tf_printing_tc; 03870 03871 list *wme_filter_list; /* kjh(CUSP-B2) */ 03872 03873 /* ----------------------- RHS Function Stuff -------------------------- */ 03874 03875 /* --- "interrupt" fun. uses this to build "reason_for_stopping" msg. --- */ 03876 #define INTERRUPT_SOURCE_SIZE 2*MAX_LEXEME_LENGTH+100 03877 char interrupt_source[INTERRUPT_SOURCE_SIZE]; 03878 03879 /* --- "make-constant-symbol" counter --- */ 03880 unsigned long mcs_counter; 03881 03882 /* ----------------------- O support stuff -------------------------- */ 03883 03884 tc_number o_support_tc; 03885 preference *rhs_prefs_from_instantiation; 03886 03887 /* ----------------------- I/O stuff -------------------------- */ 03888 03889 io_wme *collected_io_wmes; 03890 struct output_link_struct *existing_output_links; 03891 03892 struct output_link_struct *output_link_for_tc; 03893 memory_pool output_link_pool; 03894 tc_number output_link_tc_num; 03895 03896 bool output_link_changed; 03897 03898 Symbol *io_header; 03899 wme *io_header_link; 03900 03901 Symbol *io_header_input; 03902 Symbol *io_header_output; 03903 03904 memory_pool io_wme_pool; 03905 Symbol *prev_top_state; 03906 03907 /* ------------ Varible Generator stuff (in production.c) ---------------- */ 03908 03909 unsigned long current_variable_gensym_number; 03910 unsigned long gensymed_variable_count[26]; 03911 03912 /* ------------------- Experimental features ---------------------- */ 03913 int o_support_calculation_type; 03914 int attribute_preferences_mode; 03915 03916 /* ------------------- Info about the agent itself ---------------------- */ 03917 03918 char *name; /* name of this Soar agent */ 03919 int id; /* unique integer id */ 03920 unsigned long callback_error; /* an error status set during callback */ 03921 03922 /* --------- I (RBD) don't know what the following stuff is ------------ */ 03923 03924 /* String redirection */ 03925 /* 03926 bool using_input_string; 03927 char * input_string; 03928 bool using_output_string; 03929 char * output_string; 03930 */ 03931 03932 /*mvp 5-17-94 */ 03933 list *variables_set; 03934 03935 multi_attribute *multi_attributes; 03936 /* char path[MAXPATHLEN]; AGR 568 */ 03937 03938 soar_callback_array soar_callbacks; 03939 03940 alias_struct *alias_list; /* AGR 568 */ 03941 const char *alternate_input_string; 03942 const char *alternate_input_suffix; 03943 bool alternate_input_exit; /* Soar-Bugs #54, TMH */ 03944 expansion_node *lex_alias; /* AGR 568 */ 03945 bool load_errors_quit; /* AGR 527c */ 03946 dir_stack_struct *top_dir_stack; /* AGR 568 */ 03947 03948 /* RCHONG: begin 10.11 */ 03949 bool did_PE; 03950 bool soar_verbose_flag; 03951 int FIRING_TYPE; 03952 Symbol *PE_level; 03953 03954 struct ms_change_struct *ms_o_assertions; /* changes to match set */ 03955 struct ms_change_struct *ms_i_assertions; /* changes to match set */ 03956 /* RCHONG: end 10.11 */ 03957 03958 /* REW: begin 08.20.97 */ 03959 #ifndef SOAR_8_ONLY 03960 bool operand2_mode; 03961 #endif 03962 goal_stack_level active_level; 03963 goal_stack_level previous_active_level; 03964 Symbol *active_goal; 03965 Symbol *previous_active_goal; 03966 struct ms_change_struct *nil_goal_retractions; /* dll of all retractions for removed (ie nil) goals */ 03967 /* REW: end 08.20.97 */ 03968 03969 /* delineate btwn Pref/WM(propose) and Pref/WM(apply) KJC 10.05.98 */ 03970 bool applyPhase; 03971 03972 /* REW: begin 10.24.97 */ 03973 bool waitsnc; 03974 bool waitsnc_detect; 03975 /* REW: end 10.24.97 */ 03976 03977 enum ni_mode numeric_indifferent_mode; /* SW 08.19.2003 */ 03978 03979 #ifdef COUNT_KERNEL_TIMER_STOPS 03980 long kernelTimerStops; 03981 long nonKernelTimerStops; 03982 #endif 03983 #ifdef USE_AGENT_DBG_FILE 03984 FILE *dbgFile; 03985 #endif 03986 #ifdef WARN_IF_TIMERS_REPORT_ZERO 03987 bool warn_on_zero_timers; 03988 #endif 03989 03990 } agent; 03991 /*************** end of agent struct *****/ 03992 03993 typedef struct output_link_struct { 03994 struct output_link_struct *next, *prev; /* dll of all existing links */ 03995 byte status; /* current xxx_OL_STATUS */ 03996 wme *link_wme; /* points to the output link wme */ 03997 list *ids_in_tc; /* ids in TC(link) */ 03998 soar_callback *cb; /* corresponding output function */ 03999 } output_link; 04000 04001 extern agent *soar_agent; 04002 extern list *all_soar_agents; 04003 extern int agent_count; 04004 04005 extern agent *create_soar_agent(char *name); 04006 extern void destroy_soar_agent(agent * soar_agent); 04007 04008 extern char *c_interrupt_msg; 04009 04010 /* Main pgm stuff */ 04011 04012 extern void init_soar(void); 04013 extern int terminate_soar(void); 04014 04015 #ifdef __cplusplus 04016 #undef extern 04017 #endif 04018 04019 #endif /* _SOAR_H_INCLUDED */
1.3.5