00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include "soarkernel.h"
00057 #include <ctype.h>
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 unsigned long compress(unsigned long h, short num_bits)
00077 {
00078 unsigned long result;
00079
00080 if (num_bits < 16)
00081 h = (h & 0xFFFF) ^ (h >> 16);
00082 if (num_bits < 8)
00083 h = (h & 0xFF) ^ (h >> 8);
00084 result = 0;
00085 while (h) {
00086 result ^= (h & masks_for_n_low_order_bits[num_bits]);
00087 h = h >> num_bits;
00088 }
00089 return result;
00090 }
00091
00092 unsigned long hash_string(const char *s)
00093 {
00094 unsigned long h;
00095
00096 h = 0;
00097 while (*s != 0) {
00098 h = ((h << 8) | (h >> 24)) ^ (*s);
00099 s++;
00100 }
00101 return h;
00102 }
00103
00104
00105
00106
00107
00108 unsigned long hash_variable_raw_info(char *name, short num_bits)
00109 {
00110 return compress(hash_string(name), num_bits);
00111 }
00112
00113 unsigned long hash_identifier_raw_info(char name_letter, unsigned long name_number, short num_bits)
00114 {
00115 return compress(name_number | (name_letter << 24), num_bits);
00116 }
00117
00118 unsigned long hash_sym_constant_raw_info(const char *name, short num_bits)
00119 {
00120 return compress(hash_string(name), num_bits);
00121 }
00122
00123 unsigned long hash_int_constant_raw_info(long value, short num_bits)
00124 {
00125 return compress((unsigned long) value, num_bits);
00126 }
00127
00128 unsigned long hash_float_constant_raw_info(float value, short num_bits)
00129 {
00130 return compress((unsigned long) value, num_bits);
00131 }
00132
00133
00134
00135
00136
00137 unsigned long hash_variable(void *item, short num_bits)
00138 {
00139 variable *var;
00140 var = item;
00141 return compress(hash_string(var->name), num_bits);
00142 }
00143
00144 unsigned long hash_identifier(void *item, short num_bits)
00145 {
00146 identifier *id;
00147 id = item;
00148 return compress(id->name_number ^ (id->name_letter << 24), num_bits);
00149 }
00150
00151 unsigned long hash_sym_constant(void *item, short num_bits)
00152 {
00153 sym_constant *sc;
00154 sc = item;
00155 return compress(hash_string(sc->name), num_bits);
00156 }
00157
00158 unsigned long hash_int_constant(void *item, short num_bits)
00159 {
00160 int_constant *ic;
00161 ic = item;
00162 return compress((unsigned long) (ic->value), num_bits);
00163 }
00164
00165 unsigned long hash_float_constant(void *item, short num_bits)
00166 {
00167 float_constant *fc;
00168 fc = item;
00169 return compress((unsigned long) (fc->value), num_bits);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 #define get_next_symbol_hash_id() (current_agent(current_symbol_hash_id) += 137)
00179
00180 void init_symbol_tables(void)
00181 {
00182 int i;
00183
00184 current_agent(variable_hash_table) = make_hash_table(0, hash_variable);
00185 current_agent(identifier_hash_table) = make_hash_table(0, hash_identifier);
00186 current_agent(sym_constant_hash_table) = make_hash_table(0, hash_sym_constant);
00187 current_agent(int_constant_hash_table) = make_hash_table(0, hash_int_constant);
00188 current_agent(float_constant_hash_table) = make_hash_table(0, hash_float_constant);
00189
00190 init_memory_pool(¤t_agent(variable_pool), sizeof(variable), "variable");
00191 init_memory_pool(¤t_agent(identifier_pool), sizeof(identifier), "identifier");
00192 init_memory_pool(¤t_agent(sym_constant_pool), sizeof(sym_constant), "sym constant");
00193 init_memory_pool(¤t_agent(int_constant_pool), sizeof(int_constant), "int constant");
00194 init_memory_pool(¤t_agent(float_constant_pool), sizeof(float_constant), "float constant");
00195
00196 for (i = 0; i < 26; i++)
00197 current_agent(id_counter)[i] = 1;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 Symbol *find_variable(char *name)
00219 {
00220 unsigned long hash_value;
00221 Symbol *sym;
00222
00223 hash_value = hash_variable_raw_info(name, current_agent(variable_hash_table)->log2size);
00224 sym = (Symbol *) (*(current_agent(variable_hash_table)->buckets + hash_value));
00225 for (; sym != NIL; sym = sym->common.next_in_hash_table) {
00226 if (!strcmp(sym->var.name, name))
00227 return sym;
00228 }
00229 return NIL;
00230 }
00231
00232 Symbol *find_identifier(char name_letter, unsigned long name_number)
00233 {
00234 unsigned long hash_value;
00235 Symbol *sym;
00236
00237 hash_value = hash_identifier_raw_info(name_letter, name_number, current_agent(identifier_hash_table)->log2size);
00238 sym = (Symbol *) (*(current_agent(identifier_hash_table)->buckets + hash_value));
00239 for (; sym != NIL; sym = sym->common.next_in_hash_table) {
00240 if ((name_letter == sym->id.name_letter) && (name_number == sym->id.name_number))
00241 return sym;
00242 }
00243 return NIL;
00244 }
00245
00246 Symbol *find_sym_constant(const char *name)
00247 {
00248 unsigned long hash_value;
00249 Symbol *sym;
00250
00251 hash_value = hash_sym_constant_raw_info(name, current_agent(sym_constant_hash_table)->log2size);
00252 sym = (Symbol *) (*(current_agent(sym_constant_hash_table)->buckets + hash_value));
00253 for (; sym != NIL; sym = sym->common.next_in_hash_table) {
00254 if (!strcmp(sym->sc.name, name))
00255 return sym;
00256 }
00257 return NIL;
00258 }
00259
00260 Symbol *find_int_constant(long value)
00261 {
00262 unsigned long hash_value;
00263 Symbol *sym;
00264
00265 hash_value = hash_int_constant_raw_info(value, current_agent(int_constant_hash_table)->log2size);
00266 sym = (Symbol *) (*(current_agent(int_constant_hash_table)->buckets + hash_value));
00267 for (; sym != NIL; sym = sym->common.next_in_hash_table) {
00268 if (value == sym->ic.value)
00269 return sym;
00270 }
00271 return NIL;
00272 }
00273
00274 Symbol *find_float_constant(float value)
00275 {
00276 unsigned long hash_value;
00277 Symbol *sym;
00278
00279 hash_value = hash_float_constant_raw_info(value, current_agent(float_constant_hash_table)->log2size);
00280 sym = (Symbol *) (*(current_agent(float_constant_hash_table)->buckets + hash_value));
00281 for (; sym != NIL; sym = sym->common.next_in_hash_table) {
00282 if (value == sym->fc.value)
00283 return sym;
00284 }
00285 return NIL;
00286 }
00287
00288 Symbol *make_variable(char *name)
00289 {
00290 Symbol *sym;
00291
00292 sym = find_variable(name);
00293 if (sym) {
00294 sym->common.reference_count++;
00295 } else {
00296 allocate_with_pool(¤t_agent(variable_pool), &sym);
00297 sym->common.symbol_type = VARIABLE_SYMBOL_TYPE;
00298 sym->common.reference_count = 1;
00299 sym->common.hash_id = get_next_symbol_hash_id();
00300 sym->var.name = make_memory_block_for_string(name);
00301 sym->var.gensym_number = 0;
00302 sym->var.tc_num = 0;
00303 sym->var.rete_binding_locations = NIL;
00304 add_to_hash_table(current_agent(variable_hash_table), sym);
00305 }
00306 return sym;
00307 }
00308
00309 Symbol *make_new_identifier(char name_letter, goal_stack_level level)
00310 {
00311 Symbol *sym;
00312
00313 if (isalpha(name_letter)) {
00314 if (islower(name_letter))
00315 name_letter = (char) toupper(name_letter);
00316 } else {
00317 name_letter = 'I';
00318 }
00319 allocate_with_pool(¤t_agent(identifier_pool), &sym);
00320 sym->common.symbol_type = IDENTIFIER_SYMBOL_TYPE;
00321 sym->common.reference_count = 1;
00322 sym->common.hash_id = get_next_symbol_hash_id();
00323 sym->id.name_letter = name_letter;
00324 sym->id.name_number = current_agent(id_counter)[name_letter - 'A']++;
00325 sym->id.level = level;
00326 sym->id.promotion_level = level;
00327 sym->id.slots = NIL;
00328 sym->id.isa_goal = FALSE;
00329 sym->id.isa_impasse = FALSE;
00330 sym->id.isa_operator = 0;
00331 sym->id.link_count = 0;
00332 sym->id.unknown_level = NIL;
00333 sym->id.could_be_a_link_from_below = FALSE;
00334 sym->id.impasse_wmes = NIL;
00335 sym->id.higher_goal = NIL;
00336
00337 sym->id.gds = NIL;
00338
00339
00340 sym->id.saved_firing_type = NO_SAVED_PRODS;
00341 sym->id.ms_o_assertions = NIL;
00342 sym->id.ms_i_assertions = NIL;
00343 sym->id.ms_retractions = NIL;
00344
00345 sym->id.lower_goal = NIL;
00346 sym->id.operator_slot = NIL;
00347 sym->id.preferences_from_goal = NIL;
00348 sym->id.tc_num = 0;
00349 sym->id.associated_output_links = NIL;
00350 sym->id.input_wmes = NIL;
00351 add_to_hash_table(current_agent(identifier_hash_table), sym);
00352 return sym;
00353 }
00354
00355 Symbol *make_sym_constant(const char *name)
00356 {
00357 Symbol *sym;
00358
00359 sym = find_sym_constant(name);
00360 if (sym) {
00361 sym->common.reference_count++;
00362 } else {
00363 allocate_with_pool(¤t_agent(sym_constant_pool), &sym);
00364 sym->common.symbol_type = SYM_CONSTANT_SYMBOL_TYPE;
00365 sym->common.reference_count = 1;
00366 sym->common.hash_id = get_next_symbol_hash_id();
00367 sym->sc.name = make_memory_block_for_string(name);
00368 sym->sc.production = NIL;
00369 add_to_hash_table(current_agent(sym_constant_hash_table), sym);
00370 }
00371 return sym;
00372 }
00373
00374 Symbol *make_int_constant(long value)
00375 {
00376 Symbol *sym;
00377
00378 sym = find_int_constant(value);
00379 if (sym) {
00380 sym->common.reference_count++;
00381 } else {
00382 allocate_with_pool(¤t_agent(int_constant_pool), &sym);
00383 sym->common.symbol_type = INT_CONSTANT_SYMBOL_TYPE;
00384 sym->common.reference_count = 1;
00385 sym->common.hash_id = get_next_symbol_hash_id();
00386 sym->ic.value = value;
00387 add_to_hash_table(current_agent(int_constant_hash_table), sym);
00388 }
00389 return sym;
00390 }
00391
00392 Symbol *make_float_constant(float value)
00393 {
00394 Symbol *sym;
00395
00396 sym = find_float_constant(value);
00397 if (sym) {
00398 sym->common.reference_count++;
00399 } else {
00400 allocate_with_pool(¤t_agent(float_constant_pool), &sym);
00401 sym->common.symbol_type = FLOAT_CONSTANT_SYMBOL_TYPE;
00402 sym->common.reference_count = 1;
00403 sym->common.hash_id = get_next_symbol_hash_id();
00404 sym->fc.value = value;
00405 add_to_hash_table(current_agent(float_constant_hash_table), sym);
00406 }
00407 return sym;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416 void deallocate_symbol(Symbol * sym)
00417 {
00418
00419 #ifdef DEBUG_SYMBOLS
00420 print_with_symbols("\nDeallocating Symbol %y", sym);
00421 #endif
00422
00423 switch (sym->common.symbol_type) {
00424 case VARIABLE_SYMBOL_TYPE:
00425 remove_from_hash_table(current_agent(variable_hash_table), sym);
00426 free_memory_block_for_string(sym->var.name);
00427 free_with_pool(¤t_agent(variable_pool), sym);
00428 break;
00429 case IDENTIFIER_SYMBOL_TYPE:
00430 remove_from_hash_table(current_agent(identifier_hash_table), sym);
00431 free_with_pool(¤t_agent(identifier_pool), sym);
00432 break;
00433 case SYM_CONSTANT_SYMBOL_TYPE:
00434 remove_from_hash_table(current_agent(sym_constant_hash_table), sym);
00435 free_memory_block_for_string(sym->sc.name);
00436 free_with_pool(¤t_agent(sym_constant_pool), sym);
00437 break;
00438 case INT_CONSTANT_SYMBOL_TYPE:
00439 remove_from_hash_table(current_agent(int_constant_hash_table), sym);
00440 free_with_pool(¤t_agent(int_constant_pool), sym);
00441 break;
00442 case FLOAT_CONSTANT_SYMBOL_TYPE:
00443 remove_from_hash_table(current_agent(float_constant_hash_table), sym);
00444 free_with_pool(¤t_agent(float_constant_pool), sym);
00445 break;
00446 default:
00447 {
00448 char msg[MESSAGE_SIZE];
00449 strncpy(msg, "Internal error: called deallocate_symbol on non-symbol.\n", MESSAGE_SIZE);
00450 msg[MESSAGE_SIZE - 1] = 0;
00451 abort_with_fatal_error(msg);
00452 }
00453 }
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 void reset_id_counters(void)
00481 {
00482 int i;
00483
00484 if (current_agent(identifier_hash_table)->count != 0) {
00485 print("Internal warning: wanted to reset identifier generator numbers, but\n");
00486 print("there are still some identifiers allocated. (Probably a memory leak.)\n");
00487 print("(Leaving identifier numbers alone.)\n");
00488 return;
00489 }
00490 for (i = 0; i < 26; i++)
00491 current_agent(id_counter)[i] = 1;
00492 }
00493
00494 bool reset_tc_num(void *item)
00495 {
00496 Symbol *sym;
00497
00498 sym = item;
00499 if (sym->common.symbol_type == IDENTIFIER_SYMBOL_TYPE)
00500 sym->id.tc_num = 0;
00501 else if (sym->common.symbol_type == VARIABLE_SYMBOL_TYPE)
00502 sym->var.tc_num = 0;
00503 return FALSE;
00504 }
00505
00506 void reset_id_and_variable_tc_numbers(void)
00507 {
00508 do_for_all_items_in_hash_table(current_agent(identifier_hash_table), reset_tc_num);
00509 do_for_all_items_in_hash_table(current_agent(variable_hash_table), reset_tc_num);
00510 }
00511
00512 bool reset_gensym_number(void *item)
00513 {
00514 Symbol *sym;
00515
00516 sym = item;
00517 sym->var.gensym_number = 0;
00518 return FALSE;
00519 }
00520
00521 void reset_variable_gensym_numbers(void)
00522 {
00523 do_for_all_items_in_hash_table(current_agent(variable_hash_table), reset_gensym_number);
00524 }
00525
00526 bool print_sym(void *item)
00527 {
00528 print_string(symbol_to_string(item, TRUE, NIL, 0));
00529 print_string("\n");
00530 return FALSE;
00531 }
00532
00533 #define GENERATE_NEW_SYM_CONSTANT_NAME_SIZE 2048
00534 Symbol *generate_new_sym_constant(char *prefix, unsigned long *counter)
00535 {
00536 char name[GENERATE_NEW_SYM_CONSTANT_NAME_SIZE];
00537 Symbol *new;
00538
00539 for (;;) {
00540 snprintf(name, GENERATE_NEW_SYM_CONSTANT_NAME_SIZE, "%s%lu", prefix, (*counter)++);
00541 name[GENERATE_NEW_SYM_CONSTANT_NAME_SIZE - 1] = 0;
00542 if (!find_sym_constant(name))
00543 break;
00544 }
00545 new = make_sym_constant(name);
00546 return new;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555 void create_predefined_symbols(void)
00556 {
00557 current_agent(problem_space_symbol) = make_sym_constant("problem-space");
00558 current_agent(state_symbol) = make_sym_constant("state");
00559 current_agent(operator_symbol) = make_sym_constant("operator");
00560 current_agent(superstate_symbol) = make_sym_constant("superstate");
00561 current_agent(io_symbol) = make_sym_constant("io");
00562 current_agent(object_symbol) = make_sym_constant("object");
00563 current_agent(attribute_symbol) = make_sym_constant("attribute");
00564 current_agent(impasse_symbol) = make_sym_constant("impasse");
00565 current_agent(choices_symbol) = make_sym_constant("choices");
00566 current_agent(none_symbol) = make_sym_constant("none");
00567 current_agent(constraint_failure_symbol) = make_sym_constant("constraint-failure");
00568 current_agent(no_change_symbol) = make_sym_constant("no-change");
00569 current_agent(multiple_symbol) = make_sym_constant("multiple");
00570 current_agent(conflict_symbol) = make_sym_constant("conflict");
00571 current_agent(tie_symbol) = make_sym_constant("tie");
00572 current_agent(item_symbol) = make_sym_constant("item");
00573 current_agent(quiescence_symbol) = make_sym_constant("quiescence");
00574 current_agent(t_symbol) = make_sym_constant("t");
00575 current_agent(nil_symbol) = make_sym_constant("nil");
00576 current_agent(type_symbol) = make_sym_constant("type");
00577 current_agent(goal_symbol) = make_sym_constant("goal");
00578 current_agent(name_symbol) = make_sym_constant("name");
00579
00580 current_agent(ts_context_variable) = make_variable("<ts>");
00581 current_agent(to_context_variable) = make_variable("<to>");
00582 current_agent(sss_context_variable) = make_variable("<sss>");
00583 current_agent(sso_context_variable) = make_variable("<sso>");
00584 current_agent(ss_context_variable) = make_variable("<ss>");
00585 current_agent(so_context_variable) = make_variable("<so>");
00586 current_agent(s_context_variable) = make_variable("<s>");
00587 current_agent(o_context_variable) = make_variable("<o>");
00588
00589
00590 current_agent(wait_symbol) = make_variable("wait");
00591
00592 }