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 #include "soarkernel.h"
00048 #include <ctype.h>
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 void init_production_utilities(void)
00061 {
00062 init_memory_pool(¤t_agent(complex_test_pool), sizeof(complex_test), "complex test");
00063 init_memory_pool(¤t_agent(condition_pool), sizeof(condition), "condition");
00064 init_memory_pool(¤t_agent(production_pool), sizeof(production), "production");
00065 init_memory_pool(¤t_agent(action_pool), sizeof(action), "action");
00066 init_memory_pool(¤t_agent(not_pool), sizeof(not), "not");
00067 init_reorderer();
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 char first_letter_from_symbol(Symbol * sym)
00095 {
00096 switch (sym->common.symbol_type) {
00097 case VARIABLE_SYMBOL_TYPE:
00098 return *(sym->var.name + 1);
00099 case IDENTIFIER_SYMBOL_TYPE:
00100 return sym->id.name_letter;
00101 case SYM_CONSTANT_SYMBOL_TYPE:
00102 return *(sym->sc.name);
00103 default:
00104 return '*';
00105 }
00106 }
00107
00108
00109
00110
00111
00112
00113 char first_letter_from_test(test t)
00114 {
00115 complex_test *ct;
00116 cons *c;
00117 char ch;
00118
00119 if (test_is_blank_test(t))
00120 return '*';
00121 if (test_is_blank_or_equality_test(t))
00122 return first_letter_from_symbol(referent_of_equality_test(t));
00123
00124 ct = complex_test_from_test(t);
00125 switch (ct->type) {
00126 case GOAL_ID_TEST:
00127 return 's';
00128 case IMPASSE_ID_TEST:
00129 return 'i';
00130 case CONJUNCTIVE_TEST:
00131 for (c = ct->data.conjunct_list; c != NIL; c = c->rest) {
00132 ch = first_letter_from_test(c->first);
00133 if (ch != '*')
00134 return ch;
00135 }
00136 return '*';
00137 default:
00138 return '*';
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147 list *copy_symbol_list_adding_references(list * sym_list)
00148 {
00149 cons *c, *first, *prev;
00150
00151 if (!sym_list)
00152 return NIL;
00153 allocate_cons(&first);
00154 first->first = sym_list->first;
00155 symbol_add_ref((Symbol *) (first->first));
00156 sym_list = sym_list->rest;
00157 prev = first;
00158 while (sym_list) {
00159 allocate_cons(&c);
00160 prev->rest = c;
00161 c->first = sym_list->first;
00162 symbol_add_ref((Symbol *) (c->first));
00163 sym_list = sym_list->rest;
00164 prev = c;
00165 }
00166 prev->rest = NIL;
00167 return first;
00168 }
00169
00170
00171
00172
00173
00174 void deallocate_symbol_list_removing_references(list * sym_list)
00175 {
00176 cons *c;
00177
00178 while (sym_list) {
00179 c = sym_list;
00180 sym_list = sym_list->rest;
00181 symbol_remove_ref((Symbol *) (c->first));
00182 free_cons(c);
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 list *copy_test_list(cons * c)
00194 {
00195 cons *new_c;
00196
00197 if (!c)
00198 return NIL;
00199 allocate_cons(&new_c);
00200 new_c->first = copy_test(c->first);
00201 new_c->rest = copy_test_list(c->rest);
00202 return new_c;
00203 }
00204
00205
00206
00207
00208
00209 test copy_test(test t)
00210 {
00211 Symbol *referent;
00212 complex_test *ct, *new_ct;
00213
00214 if (test_is_blank_test(t))
00215 return make_blank_test();
00216
00217 if (test_is_blank_or_equality_test(t)) {
00218 referent = referent_of_equality_test(t);
00219 return make_equality_test(referent);
00220 }
00221
00222 ct = complex_test_from_test(t);
00223
00224 allocate_with_pool(¤t_agent(complex_test_pool), &new_ct);
00225 new_ct->type = ct->type;
00226 switch (ct->type) {
00227 case GOAL_ID_TEST:
00228 case IMPASSE_ID_TEST:
00229 break;
00230 case DISJUNCTION_TEST:
00231 new_ct->data.disjunction_list = copy_symbol_list_adding_references(ct->data.disjunction_list);
00232 break;
00233 case CONJUNCTIVE_TEST:
00234 new_ct->data.conjunct_list = copy_test_list(ct->data.conjunct_list);
00235 break;
00236 default:
00237 new_ct->data.referent = ct->data.referent;
00238 symbol_add_ref(ct->data.referent);
00239 break;
00240 }
00241 return make_test_from_complex_test(new_ct);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251 test copy_test_removing_goal_impasse_tests(test t, bool * removed_goal, bool * removed_impasse)
00252 {
00253 complex_test *ct, *new_ct;
00254 cons *c;
00255 test new_t, temp;
00256
00257 if (test_is_blank_or_equality_test(t))
00258 return copy_test(t);
00259
00260 ct = complex_test_from_test(t);
00261
00262 switch (ct->type) {
00263 case GOAL_ID_TEST:
00264 *removed_goal = TRUE;
00265 return make_blank_test();
00266 case IMPASSE_ID_TEST:
00267 *removed_impasse = TRUE;
00268 return make_blank_test();
00269
00270 case CONJUNCTIVE_TEST:
00271 new_t = make_blank_test();
00272 for (c = ct->data.conjunct_list; c != NIL; c = c->rest) {
00273 temp = copy_test_removing_goal_impasse_tests(c->first, removed_goal, removed_impasse);
00274 if (!test_is_blank_test(temp))
00275 add_new_test_to_test(&new_t, temp);
00276 }
00277 if (test_is_complex_test(new_t)) {
00278 new_ct = complex_test_from_test(new_t);
00279 if (new_ct->type == CONJUNCTIVE_TEST)
00280 new_ct->data.conjunct_list = destructively_reverse_list(new_ct->data.conjunct_list);
00281 }
00282 return new_t;
00283
00284 default:
00285 return copy_test(t);
00286 }
00287 }
00288
00289
00290
00291
00292
00293 void deallocate_test(test t)
00294 {
00295 cons *c, *next_c;
00296 complex_test *ct;
00297
00298 if (test_is_blank_test(t))
00299 return;
00300 if (test_is_blank_or_equality_test(t)) {
00301 symbol_remove_ref(referent_of_equality_test(t));
00302 return;
00303 }
00304
00305 ct = complex_test_from_test(t);
00306
00307 switch (ct->type) {
00308 case GOAL_ID_TEST:
00309 case IMPASSE_ID_TEST:
00310 break;
00311 case DISJUNCTION_TEST:
00312 deallocate_symbol_list_removing_references(ct->data.disjunction_list);
00313 break;
00314 case CONJUNCTIVE_TEST:
00315 c = ct->data.conjunct_list;
00316 while (c) {
00317 next_c = c->rest;
00318 deallocate_test(c->first);
00319 free_cons(c);
00320 c = next_c;
00321 }
00322 break;
00323 default:
00324 symbol_remove_ref(ct->data.referent);
00325 break;
00326 }
00327 free_with_pool(¤t_agent(complex_test_pool), ct);
00328 }
00329
00330
00331 #define quickly_deallocate_test(t) { \
00332 if (! test_is_blank_test(t)) { \
00333 if (test_is_blank_or_equality_test(t)) { \
00334 symbol_remove_ref (referent_of_equality_test(t)); \
00335 } else { \
00336 deallocate_test (t); } } }
00337
00338
00339
00340
00341
00342
00343
00344 void add_new_test_to_test(test * t, test add_me)
00345 {
00346 complex_test *ct = NULL;
00347 cons *c;
00348 bool already_a_conjunctive_test;
00349
00350 if (test_is_blank_test(add_me))
00351 return;
00352
00353 if (test_is_blank_test(*t)) {
00354 *t = add_me;
00355 return;
00356 }
00357
00358
00359 already_a_conjunctive_test = FALSE;
00360 if (test_is_complex_test(*t)) {
00361 ct = complex_test_from_test(*t);
00362 if (ct->type == CONJUNCTIVE_TEST)
00363 already_a_conjunctive_test = TRUE;
00364 }
00365
00366 if (!already_a_conjunctive_test) {
00367 allocate_with_pool(¤t_agent(complex_test_pool), &ct);
00368 ct->type = CONJUNCTIVE_TEST;
00369 allocate_cons(&c);
00370 ct->data.conjunct_list = c;
00371 c->first = *t;
00372 c->rest = NIL;
00373 *t = make_test_from_complex_test(ct);
00374 }
00375
00376
00377
00378 allocate_cons(&c);
00379 c->first = add_me;
00380 c->rest = ct->data.conjunct_list;
00381 ct->data.conjunct_list = c;
00382 }
00383
00384
00385
00386
00387
00388
00389 void add_new_test_to_test_if_not_already_there(test * t, test add_me)
00390 {
00391 complex_test *ct;
00392 cons *c;
00393
00394 if (tests_are_equal(*t, add_me)) {
00395 deallocate_test(add_me);
00396 return;
00397 }
00398
00399 if (test_is_complex_test(*t)) {
00400 ct = complex_test_from_test(*t);
00401 if (ct->type == CONJUNCTIVE_TEST)
00402 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00403 if (tests_are_equal(c->first, add_me)) {
00404 deallocate_test(add_me);
00405 return;
00406 }
00407 }
00408
00409 add_new_test_to_test(t, add_me);
00410 }
00411
00412
00413
00414
00415
00416 bool tests_are_equal(test t1, test t2)
00417 {
00418 cons *c1, *c2;
00419 complex_test *ct1, *ct2;
00420
00421 if (test_is_blank_or_equality_test(t1))
00422 return (bool) (t1 == t2);
00423
00424 ct1 = complex_test_from_test(t1);
00425 ct2 = complex_test_from_test(t2);
00426
00427 if (ct1->type != ct2->type)
00428 return FALSE;
00429
00430 switch (ct1->type) {
00431 case GOAL_ID_TEST:
00432 return TRUE;
00433 case IMPASSE_ID_TEST:
00434 return TRUE;
00435
00436 case DISJUNCTION_TEST:
00437 for (c1 = ct1->data.disjunction_list, c2 = ct2->data.disjunction_list;
00438 ((c1 != NIL) && (c2 != NIL)); c1 = c1->rest, c2 = c2->rest)
00439 if (c1->first != c2->first)
00440 return FALSE;
00441 if (c1 == c2)
00442 return TRUE;
00443 return FALSE;
00444
00445 case CONJUNCTIVE_TEST:
00446 for (c1 = ct1->data.conjunct_list, c2 = ct2->data.conjunct_list;
00447 ((c1 != NIL) && (c2 != NIL)); c1 = c1->rest, c2 = c2->rest)
00448 if (!tests_are_equal(c1->first, c2->first))
00449 return FALSE;
00450 if (c1 == c2)
00451 return TRUE;
00452 return FALSE;
00453
00454 default:
00455 if (ct1->data.referent == ct2->data.referent)
00456 return TRUE;
00457 return FALSE;
00458 }
00459 }
00460
00461
00462
00463
00464
00465 unsigned long hash_test(test t)
00466 {
00467 complex_test *ct;
00468 cons *c;
00469 unsigned long result;
00470
00471 if (test_is_blank_test(t))
00472 return 0;
00473
00474 if (test_is_blank_or_equality_test(t))
00475 return (referent_of_equality_test(t))->common.hash_id;
00476
00477 ct = complex_test_from_test(t);
00478
00479 switch (ct->type) {
00480 case GOAL_ID_TEST:
00481 return 34894895;
00482 case IMPASSE_ID_TEST:
00483 return 2089521;
00484 case DISJUNCTION_TEST:
00485 result = 7245;
00486 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00487 result = result + ((Symbol *) (c->first))->common.hash_id;
00488 return result;
00489 case CONJUNCTIVE_TEST:
00490 result = 100276;
00491 for (c = ct->data.disjunction_list; c != NIL; c = c->rest)
00492 result = result + hash_test(c->first);
00493 return result;
00494 case NOT_EQUAL_TEST:
00495 case LESS_TEST:
00496 case GREATER_TEST:
00497 case LESS_OR_EQUAL_TEST:
00498 case GREATER_OR_EQUAL_TEST:
00499 case SAME_TYPE_TEST:
00500 return (ct->type << 24) + ct->data.referent->common.hash_id;
00501 default:
00502 {
00503 char msg[MESSAGE_SIZE];
00504 strncpy(msg, "production.c: Error: bad test type in hash_test\n", MESSAGE_SIZE);
00505 msg[MESSAGE_SIZE - 1] = 0;
00506 abort_with_fatal_error(msg);
00507 }
00508 }
00509 return 0;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 #define NON_EQUAL_TEST_RETURN_VAL 0
00521
00522 unsigned long canonical_test(test t)
00523 {
00524 Symbol *sym;
00525
00526 if (test_is_blank_test(t))
00527 return NON_EQUAL_TEST_RETURN_VAL;
00528
00529 if (test_is_blank_or_equality_test(t)) {
00530 sym = referent_of_equality_test(t);
00531 if (sym->common.symbol_type == SYM_CONSTANT_SYMBOL_TYPE ||
00532 sym->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE ||
00533 sym->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
00534 return (sym->common.hash_id);
00535 } else
00536 return NON_EQUAL_TEST_RETURN_VAL;
00537 }
00538 return NON_EQUAL_TEST_RETURN_VAL;
00539 }
00540
00541 #define CANONICAL_TEST_ORDER canonical_test
00542
00543
00544
00545
00546
00547 bool canonical_cond_greater(condition * c1, condition * c2)
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 {
00631 unsigned long test_order_1, test_order_2;
00632
00633 if ((test_order_1 = CANONICAL_TEST_ORDER(c1->data.tests.attr_test)) <
00634 (test_order_2 = CANONICAL_TEST_ORDER(c2->data.tests.attr_test))) {
00635 return TRUE;
00636 } else if (test_order_1 == test_order_2 &&
00637 CANONICAL_TEST_ORDER(c1->data.tests.value_test) < CANONICAL_TEST_ORDER(c2->data.tests.value_test)) {
00638 return TRUE;
00639 }
00640 return FALSE;
00641 }
00642
00643
00644
00645
00646
00647
00648
00649 bool test_includes_equality_test_for_symbol(test t, Symbol * sym)
00650 {
00651 cons *c;
00652 complex_test *ct;
00653
00654 if (test_is_blank_test(t))
00655 return FALSE;
00656
00657 if (test_is_blank_or_equality_test(t)) {
00658 if (sym)
00659 return (bool) (referent_of_equality_test(t) == sym);
00660 return TRUE;
00661 }
00662
00663 ct = complex_test_from_test(t);
00664
00665 if (ct->type == CONJUNCTIVE_TEST) {
00666 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00667 if (test_includes_equality_test_for_symbol(c->first, sym))
00668 return TRUE;
00669 }
00670 return FALSE;
00671 }
00672
00673
00674
00675
00676
00677
00678 bool test_includes_goal_or_impasse_id_test(test t, bool look_for_goal, bool look_for_impasse)
00679 {
00680 complex_test *ct;
00681 cons *c;
00682
00683 if (test_is_blank_or_equality_test(t))
00684 return FALSE;
00685 ct = complex_test_from_test(t);
00686 if (look_for_goal && (ct->type == GOAL_ID_TEST))
00687 return TRUE;
00688 if (look_for_impasse && (ct->type == IMPASSE_ID_TEST))
00689 return TRUE;
00690 if (ct->type == CONJUNCTIVE_TEST) {
00691 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00692 if (test_includes_goal_or_impasse_id_test(c->first, look_for_goal, look_for_impasse))
00693 return TRUE;
00694 return FALSE;
00695 }
00696 return FALSE;
00697 }
00698
00699
00700
00701
00702
00703
00704
00705 test copy_of_equality_test_found_in_test(test t)
00706 {
00707 complex_test *ct;
00708 cons *c;
00709 char msg[MESSAGE_SIZE];
00710
00711 if (test_is_blank_test(t)) {
00712 strncpy(msg, "Internal error: can't find equality test in test\n", MESSAGE_SIZE);
00713 msg[MESSAGE_SIZE - 1] = 0;
00714 abort_with_fatal_error(msg);
00715 }
00716 if (test_is_blank_or_equality_test(t))
00717 return copy_test(t);
00718 ct = complex_test_from_test(t);
00719 if (ct->type == CONJUNCTIVE_TEST) {
00720 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00721 if ((!test_is_blank_test((test) (c->first))) && (test_is_blank_or_equality_test((test) (c->first))))
00722 return copy_test(c->first);
00723 }
00724 strncpy(msg, "Internal error: can't find equality test in test\n", MESSAGE_SIZE);
00725 msg[MESSAGE_SIZE - 1] = 0;
00726 abort_with_fatal_error(msg);
00727 return 0;
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 void deallocate_condition_list(condition * cond_list)
00741 {
00742 condition *c;
00743
00744 while (cond_list) {
00745 c = cond_list;
00746
00747 cond_list = cond_list->next;
00748 if (c->type == CONJUNCTIVE_NEGATION_CONDITION) {
00749 deallocate_condition_list(c->data.ncc.top);
00750 } else {
00751 quickly_deallocate_test(c->data.tests.id_test);
00752 quickly_deallocate_test(c->data.tests.attr_test);
00753 quickly_deallocate_test(c->data.tests.value_test);
00754 }
00755 free_with_pool(¤t_agent(condition_pool), c);
00756 }
00757 }
00758
00759
00760
00761
00762
00763 condition *copy_condition(condition * cond)
00764 {
00765 condition *new;
00766
00767 if (!cond)
00768 return NIL;
00769 allocate_with_pool(¤t_agent(condition_pool), &new);
00770 new->type = cond->type;
00771
00772 switch (cond->type) {
00773 case POSITIVE_CONDITION:
00774 new->bt = cond->bt;
00775
00776 case NEGATIVE_CONDITION:
00777 new->data.tests.id_test = copy_test(cond->data.tests.id_test);
00778 new->data.tests.attr_test = copy_test(cond->data.tests.attr_test);
00779 new->data.tests.value_test = copy_test(cond->data.tests.value_test);
00780 new->test_for_acceptable_preference = cond->test_for_acceptable_preference;
00781 break;
00782 case CONJUNCTIVE_NEGATION_CONDITION:
00783 copy_condition_list(cond->data.ncc.top, &(new->data.ncc.top), &(new->data.ncc.bottom));
00784 break;
00785 }
00786 return new;
00787 }
00788
00789
00790
00791
00792
00793
00794 void copy_condition_list(condition * top_cond, condition ** dest_top, condition ** dest_bottom)
00795 {
00796 condition *new, *prev;
00797
00798 prev = NIL;
00799 while (top_cond) {
00800 new = copy_condition(top_cond);
00801 if (prev)
00802 prev->next = new;
00803 else
00804 *dest_top = new;
00805 new->prev = prev;
00806 prev = new;
00807 top_cond = top_cond->next;
00808 }
00809 if (prev)
00810 prev->next = NIL;
00811 else
00812 *dest_top = NIL;
00813 *dest_bottom = prev;
00814 }
00815
00816
00817
00818
00819
00820 bool conditions_are_equal(condition * c1, condition * c2)
00821 {
00822 if (c1->type != c2->type)
00823 return FALSE;
00824 switch (c1->type) {
00825 case POSITIVE_CONDITION:
00826 case NEGATIVE_CONDITION:
00827 if (!tests_are_equal(c1->data.tests.id_test, c2->data.tests.id_test))
00828 return FALSE;
00829 if (!tests_are_equal(c1->data.tests.attr_test, c2->data.tests.attr_test))
00830 return FALSE;
00831 if (!tests_are_equal(c1->data.tests.value_test, c2->data.tests.value_test))
00832 return FALSE;
00833 if (c1->test_for_acceptable_preference != c2->test_for_acceptable_preference)
00834 return FALSE;
00835 return TRUE;
00836
00837 case CONJUNCTIVE_NEGATION_CONDITION:
00838 for (c1 = c1->data.ncc.top, c2 = c2->data.ncc.top; ((c1 != NIL) && (c2 != NIL)); c1 = c1->next, c2 = c2->next)
00839 if (!conditions_are_equal(c1, c2))
00840 return FALSE;
00841 if (c1 == c2)
00842 return TRUE;
00843 return FALSE;
00844 }
00845 return FALSE;
00846 }
00847
00848
00849
00850
00851
00852 unsigned long hash_condition(condition * cond)
00853 {
00854 unsigned long result;
00855 condition *c;
00856
00857 switch (cond->type) {
00858 case POSITIVE_CONDITION:
00859 result = hash_test(cond->data.tests.id_test);
00860 result = (result << 24) | (result >> 8);
00861 result ^= hash_test(cond->data.tests.attr_test);
00862 result = (result << 24) | (result >> 8);
00863 result ^= hash_test(cond->data.tests.value_test);
00864 if (cond->test_for_acceptable_preference)
00865 result++;
00866 break;
00867 case NEGATIVE_CONDITION:
00868 result = 1267818;
00869 result ^= hash_test(cond->data.tests.id_test);
00870 result = (result << 24) | (result >> 8);
00871 result ^= hash_test(cond->data.tests.attr_test);
00872 result = (result << 24) | (result >> 8);
00873 result ^= hash_test(cond->data.tests.value_test);
00874 if (cond->test_for_acceptable_preference)
00875 result++;
00876 break;
00877 case CONJUNCTIVE_NEGATION_CONDITION:
00878 result = 82348149;
00879 for (c = cond->data.ncc.top; c != NIL; c = c->next) {
00880 result ^= hash_condition(c);
00881 result = (result << 24) | (result >> 8);
00882 }
00883 break;
00884 default:
00885 {
00886 char msg[MESSAGE_SIZE];
00887 strncpy(msg, "Internal error: bad cond type in hash_condition\n", MESSAGE_SIZE);
00888 msg[MESSAGE_SIZE - 1] = 0;
00889 abort_with_fatal_error(msg);
00890 }
00891 result = 0;
00892 }
00893 return result;
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 void deallocate_rhs_value(rhs_value rv)
00907 {
00908 cons *c;
00909 list *fl;
00910
00911 if (rhs_value_is_reteloc(rv))
00912 return;
00913 if (rhs_value_is_unboundvar(rv))
00914 return;
00915 if (rhs_value_is_funcall(rv)) {
00916 fl = rhs_value_to_funcall_list(rv);
00917 for (c = fl->rest; c != NIL; c = c->rest)
00918 deallocate_rhs_value(c->first);
00919 free_list(fl);
00920 } else {
00921 symbol_remove_ref(rhs_value_to_symbol(rv));
00922 }
00923 }
00924
00925
00926
00927
00928
00929 rhs_value copy_rhs_value(rhs_value rv)
00930 {
00931 cons *c, *new_c, *prev_new_c;
00932 list *fl, *new_fl;
00933
00934 if (rhs_value_is_reteloc(rv))
00935 return rv;
00936 if (rhs_value_is_unboundvar(rv))
00937 return rv;
00938 if (rhs_value_is_funcall(rv)) {
00939 fl = rhs_value_to_funcall_list(rv);
00940 allocate_cons(&new_fl);
00941 new_fl->first = fl->first;
00942 prev_new_c = new_fl;
00943 for (c = fl->rest; c != NIL; c = c->rest) {
00944 allocate_cons(&new_c);
00945 new_c->first = copy_rhs_value(c->first);
00946 prev_new_c->rest = new_c;
00947 prev_new_c = new_c;
00948 }
00949 prev_new_c->rest = NIL;
00950 return funcall_list_to_rhs_value(new_fl);
00951 } else {
00952 symbol_add_ref(rhs_value_to_symbol(rv));
00953 return rv;
00954 }
00955 }
00956
00957
00958
00959
00960
00961 void deallocate_action_list(action * actions)
00962 {
00963 action *a;
00964
00965 while (actions) {
00966 a = actions;
00967 actions = actions->next;
00968 if (a->type == FUNCALL_ACTION) {
00969 deallocate_rhs_value(a->value);
00970 } else {
00971
00972 deallocate_rhs_value(a->id);
00973 deallocate_rhs_value(a->attr);
00974 deallocate_rhs_value(a->value);
00975 if (preference_is_binary(a->preference_type))
00976 deallocate_rhs_value(a->referent);
00977 }
00978 free_with_pool(¤t_agent(action_pool), a);
00979 }
00980 }
00981
00982
00983
00984
00985
00986
00987 char first_letter_from_rhs_value(rhs_value rv)
00988 {
00989 if (rhs_value_is_symbol(rv))
00990 return first_letter_from_symbol(rhs_value_to_symbol(rv));
00991 return '*';
00992 }
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 void deallocate_list_of_nots(not * nots)
01005 {
01006 not *temp;
01007
01008 while (nots) {
01009 temp = nots;
01010 nots = nots->next;
01011 symbol_remove_ref(temp->s1);
01012 symbol_remove_ref(temp->s2);
01013 free_with_pool(¤t_agent(not_pool), temp);
01014 }
01015 }
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 tc_number current_tc_number = 0;
01040
01041 tc_number get_new_tc_number(void)
01042 {
01043 current_tc_number++;
01044 if (current_tc_number == 0) {
01045 reset_id_and_variable_tc_numbers();
01046 current_tc_number = 1;
01047 }
01048 return current_tc_number;
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 #define mark_identifier_if_unmarked(ident,tc,id_list) { \
01075 if ((ident)->id.tc_num != (tc)) { \
01076 (ident)->id.tc_num = (tc); \
01077 if (id_list) push ((ident),(*(id_list))); } }
01078
01079 #define mark_variable_if_unmarked(v,tc,var_list) { \
01080 if ((v)->var.tc_num != (tc)) { \
01081 (v)->var.tc_num = (tc); \
01082 if (var_list) push ((v),(*(var_list))); } }
01083
01084 void unmark_identifiers_and_free_list(list * id_list)
01085 {
01086 cons *next;
01087 Symbol *sym;
01088
01089 while (id_list) {
01090 sym = id_list->first;
01091 next = id_list->rest;
01092 free_cons(id_list);
01093 sym->id.tc_num = 0;
01094 id_list = next;
01095 }
01096 }
01097
01098 void unmark_variables_and_free_list(list * var_list)
01099 {
01100 cons *next;
01101 Symbol *sym;
01102
01103 while (var_list) {
01104 sym = var_list->first;
01105 next = var_list->rest;
01106 free_cons(var_list);
01107 sym->var.tc_num = 0;
01108 var_list = next;
01109 }
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 void add_bound_variables_in_test(test t, tc_number tc, list ** var_list)
01122 {
01123 cons *c;
01124 Symbol *referent;
01125 complex_test *ct;
01126
01127 if (test_is_blank_test(t))
01128 return;
01129
01130 if (test_is_blank_or_equality_test(t)) {
01131 referent = referent_of_equality_test(t);
01132 if (referent->common.symbol_type == VARIABLE_SYMBOL_TYPE)
01133 mark_variable_if_unmarked(referent, tc, var_list);
01134 return;
01135 }
01136
01137 ct = complex_test_from_test(t);
01138 if (ct->type == CONJUNCTIVE_TEST) {
01139 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
01140 add_bound_variables_in_test(c->first, tc, var_list);
01141 }
01142 }
01143
01144 void add_bound_variables_in_condition(condition * c, tc_number tc, list ** var_list)
01145 {
01146 if (c->type != POSITIVE_CONDITION)
01147 return;
01148 add_bound_variables_in_test(c->data.tests.id_test, tc, var_list);
01149 add_bound_variables_in_test(c->data.tests.attr_test, tc, var_list);
01150 add_bound_variables_in_test(c->data.tests.value_test, tc, var_list);
01151 }
01152
01153 void add_bound_variables_in_condition_list(condition * cond_list, tc_number tc, list ** var_list)
01154 {
01155 condition *c;
01156
01157 for (c = cond_list; c != NIL; c = c->next)
01158 add_bound_variables_in_condition(c, tc, var_list);
01159 }
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170 void add_all_variables_in_test(test t, tc_number tc, list ** var_list)
01171 {
01172 cons *c;
01173 Symbol *referent;
01174 complex_test *ct;
01175
01176 if (test_is_blank_test(t))
01177 return;
01178
01179 if (test_is_blank_or_equality_test(t)) {
01180 referent = referent_of_equality_test(t);
01181 if (referent->common.symbol_type == VARIABLE_SYMBOL_TYPE)
01182 mark_variable_if_unmarked(referent, tc, var_list);
01183 return;
01184 }
01185
01186 ct = complex_test_from_test(t);
01187
01188 switch (ct->type) {
01189 case GOAL_ID_TEST:
01190 case IMPASSE_ID_TEST:
01191 case DISJUNCTION_TEST:
01192 break;
01193
01194 case CONJUNCTIVE_TEST:
01195 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
01196 add_all_variables_in_test(c->first, tc, var_list);
01197 break;
01198
01199 default:
01200
01201 referent = ct->data.referent;
01202 if (referent->common.symbol_type == VARIABLE_SYMBOL_TYPE)
01203 mark_variable_if_unmarked(referent, tc, var_list);
01204 break;
01205 }
01206 }
01207
01208 void add_all_variables_in_condition_list(condition * cond_list, tc_number tc, list ** var_list);
01209
01210 void add_all_variables_in_condition(condition * c, tc_number tc, list ** var_list)
01211 {
01212 if (c->type == CONJUNCTIVE_NEGATION_CONDITION) {
01213 add_all_variables_in_condition_list(c->data.ncc.top, tc, var_list);
01214 } else {
01215 add_all_variables_in_test(c->data.tests.id_test, tc, var_list);
01216 add_all_variables_in_test(c->data.tests.attr_test, tc, var_list);
01217 add_all_variables_in_test(c->data.tests.value_test, tc, var_list);
01218 }
01219 }
01220
01221 void add_all_variables_in_condition_list(condition * cond_list, tc_number tc, list ** var_list)
01222 {
01223 condition *c;
01224
01225 for (c = cond_list; c != NIL; c = c->next)
01226 add_all_variables_in_condition(c, tc, var_list);
01227 }
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 void add_all_variables_in_rhs_value(rhs_value rv, tc_number tc, list ** var_list)
01243 {
01244 list *fl;
01245 cons *c;
01246 Symbol *sym;
01247
01248 if (rhs_value_is_symbol(rv)) {
01249
01250 sym = rhs_value_to_symbol(rv);
01251 if (sym->common.symbol_type == VARIABLE_SYMBOL_TYPE)
01252 mark_variable_if_unmarked(sym, tc, var_list);
01253 } else {
01254
01255 fl = rhs_value_to_funcall_list(rv);
01256 for (c = fl->rest; c != NIL; c = c->rest)
01257 add_all_variables_in_rhs_value(c->first, tc, var_list);
01258 }
01259 }
01260
01261 void add_all_variables_in_action(action * a, tc_number tc, list ** var_list)
01262 {
01263 Symbol *id;
01264
01265 if (a->type == MAKE_ACTION) {
01266
01267 id = rhs_value_to_symbol(a->id);
01268 if (id->common.symbol_type == VARIABLE_SYMBOL_TYPE)
01269 mark_variable_if_unmarked(id, tc, var_list);
01270 add_all_variables_in_rhs_value(a->attr, tc, var_list);
01271 add_all_variables_in_rhs_value(a->value, tc, var_list);
01272 if (preference_is_binary(a->preference_type))
01273 add_all_variables_in_rhs_value(a->referent, tc, var_list);
01274 } else {
01275
01276 add_all_variables_in_rhs_value(a->value, tc, var_list);
01277 }
01278 }
01279
01280 void add_all_variables_in_action_list(action * actions, tc_number tc, list ** var_list)
01281 {
01282 action *a;
01283
01284 for (a = actions; a != NIL; a = a->next)
01285 add_all_variables_in_action(a, tc, var_list);
01286 }
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 void add_symbol_to_tc(Symbol * sym, tc_number tc, list ** id_list, list ** var_list)
01318 {
01319 if (sym->common.symbol_type == VARIABLE_SYMBOL_TYPE) {
01320 mark_variable_if_unmarked(sym, tc, var_list);
01321 } else if (sym->common.symbol_type == IDENTIFIER_SYMBOL_TYPE) {
01322 mark_identifier_if_unmarked(sym, tc, id_list);
01323 }
01324 }
01325
01326 void add_test_to_tc(test t, tc_number tc, list ** id_list, list ** var_list)
01327 {
01328 cons *c;
01329 complex_test *ct;
01330
01331 if (test_is_blank_test(t))
01332 return;
01333
01334 if (test_is_blank_or_equality_test(t)) {
01335 add_symbol_to_tc(referent_of_equality_test(t), tc, id_list, var_list);
01336 return;
01337 }
01338
01339 ct = complex_test_from_test(t);
01340 if (ct->type == CONJUNCTIVE_TEST) {
01341 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
01342 add_test_to_tc(c->first, tc, id_list, var_list);
01343 }
01344 }
01345
01346 void add_cond_to_tc(condition * c, tc_number tc, list ** id_list, list ** var_list)
01347 {
01348 if (c->type == POSITIVE_CONDITION) {
01349 add_test_to_tc(c->data.tests.id_test, tc, id_list, var_list);
01350 add_test_to_tc(c->data.tests.value_test, tc, id_list, var_list);
01351 }
01352 }
01353
01354 void add_action_to_tc(action * a, tc_number tc, list ** id_list, list ** var_list)
01355 {
01356 if (a->type != MAKE_ACTION)
01357 return;
01358 add_symbol_to_tc(rhs_value_to_symbol(a->id), tc, id_list, var_list);
01359 if (rhs_value_is_symbol(a->value))
01360 add_symbol_to_tc(rhs_value_to_symbol(a->value), tc, id_list, var_list);
01361 if (preference_is_binary(a->preference_type))
01362 if (rhs_value_is_symbol(a->referent))
01363 add_symbol_to_tc(rhs_value_to_symbol(a->referent), tc, id_list, var_list);
01364 }
01365
01366 bool symbol_is_in_tc(Symbol * sym, tc_number tc)
01367 {
01368 if (sym->common.symbol_type == VARIABLE_SYMBOL_TYPE)
01369 return (bool) (sym->var.tc_num == tc);
01370 if (sym->common.symbol_type == IDENTIFIER_SYMBOL_TYPE)
01371 return (bool) (sym->id.tc_num == tc);
01372 return FALSE;
01373 }
01374
01375 bool test_is_in_tc(test t, tc_number tc)
01376 {
01377 cons *c;
01378 complex_test *ct;
01379
01380 if (test_is_blank_test(t))
01381 return FALSE;
01382 if (test_is_blank_or_equality_test(t)) {
01383 return symbol_is_in_tc(referent_of_equality_test(t), tc);
01384 }
01385
01386 ct = complex_test_from_test(t);
01387 if (ct->type == CONJUNCTIVE_TEST) {
01388 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
01389 if (test_is_in_tc(c->first, tc))
01390 return TRUE;
01391 return FALSE;
01392 }
01393 return FALSE;
01394 }
01395
01396 bool cond_is_in_tc(condition * cond, tc_number tc)
01397 {
01398 condition *c;
01399 bool anything_changed;
01400 bool result;
01401 list *new_ids, *new_vars;
01402
01403 if (cond->type != CONJUNCTIVE_NEGATION_CONDITION)
01404 return test_is_in_tc(cond->data.tests.id_test, tc);
01405
01406
01407 new_ids = NIL;
01408 new_vars = NIL;
01409 for (c = cond->data.ncc.top; c != NIL; c = c->next)
01410 c->already_in_tc = FALSE;
01411 for (;;) {
01412 anything_changed = FALSE;
01413 for (c = cond->data.ncc.top; c != NIL; c = c->next)
01414 if (!c->already_in_tc)
01415 if (cond_is_in_tc(c, tc)) {
01416 add_cond_to_tc(c, tc, &new_ids, &new_vars);
01417 c->already_in_tc = TRUE;
01418 anything_changed = TRUE;
01419 }
01420 if (!anything_changed)
01421 break;
01422 }
01423
01424
01425 result = TRUE;
01426 for (c = cond->data.ncc.top; c != NIL; c = c->next)
01427 if (!c->already_in_tc)
01428 result = FALSE;
01429
01430
01431 unmark_identifiers_and_free_list(new_ids);
01432 unmark_variables_and_free_list(new_vars);
01433
01434 return result;
01435 }
01436
01437 bool action_is_in_tc(action * a, tc_number tc)
01438 {
01439 if (a->type != MAKE_ACTION)
01440 return FALSE;
01441 return symbol_is_in_tc(rhs_value_to_symbol(a->id), tc);
01442 }
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462 void reset_variable_generator(condition * conds_with_vars_to_avoid, action * actions_with_vars_to_avoid)
01463 {
01464 tc_number tc;
01465 list *var_list;
01466 cons *c;
01467 int i;
01468
01469
01470 for (i = 0; i < 26; i++)
01471 current_agent(gensymed_variable_count)[i] = 1;
01472 current_agent(current_variable_gensym_number)++;
01473 if (current_agent(current_variable_gensym_number) == 0) {
01474 reset_variable_gensym_numbers();
01475 current_agent(current_variable_gensym_number) = 1;
01476 }
01477
01478
01479 tc = get_new_tc_number();
01480 var_list = NIL;
01481 add_all_variables_in_condition_list(conds_with_vars_to_avoid, tc, &var_list);
01482 add_all_variables_in_action_list(actions_with_vars_to_avoid, tc, &var_list);
01483 for (c = var_list; c != NIL; c = c->rest)
01484 ((Symbol *) (c->first))->var.gensym_number = current_agent(current_variable_gensym_number);
01485 free_list(var_list);
01486 }
01487
01488 #define NAME_BUF_SIZE 200
01489 Symbol *generate_new_variable(char *prefix)
01490 {
01491 char name[NAME_BUF_SIZE];
01492 Symbol *new;
01493 char first_letter;
01494
01495 first_letter = *prefix;
01496 if (isalpha(first_letter)) {
01497 if (isupper(first_letter))
01498 first_letter = (char) tolower(first_letter);
01499 } else {
01500 first_letter = 'v';
01501 }
01502
01503 for (;;) {
01504 snprintf(name, NAME_BUF_SIZE, "<%s%lu>", prefix, current_agent(gensymed_variable_count)[first_letter - 'a']++);
01505 name[NAME_BUF_SIZE - 1] = 0;
01506 new = make_variable(name);
01507 if (new->var.gensym_number != current_agent(current_variable_gensym_number))
01508 break;
01509 symbol_remove_ref(new);
01510 }
01511
01512 new->var.current_binding_value = NIL;
01513 new->var.gensym_number = current_agent(current_variable_gensym_number);
01514 return new;
01515 }
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 extern char *name_of_production_being_reordered;
01537
01538 production *make_production(byte type,
01539 Symbol * name,
01540 condition ** lhs_top, condition ** lhs_bottom, action ** rhs_top, bool reorder_nccs)
01541 {
01542 production *p;
01543 tc_number tc;
01544 action *a;
01545
01546 name_of_production_being_reordered = name->sc.name;
01547
01548 if (type != JUSTIFICATION_PRODUCTION_TYPE) {
01549 reset_variable_generator(*lhs_top, *rhs_top);
01550 tc = get_new_tc_number();
01551 add_bound_variables_in_condition_list(*lhs_top, tc, NIL);
01552 if (!reorder_action_list(rhs_top, tc))
01553 return NIL;
01554 if (!reorder_lhs(lhs_top, lhs_bottom, reorder_nccs))
01555 return NIL;
01556
01557 #ifdef DO_COMPILE_TIME_O_SUPPORT_CALCS
01558 calculate_compile_time_o_support(*lhs_top, *rhs_top);
01559 #ifdef LIST_COMPILE_TIME_O_SUPPORT_FAILURES
01560 for (a = *rhs_top; a != NIL; a = a->next)
01561 if ((a->type == MAKE_ACTION) && (a->support == UNKNOWN_SUPPORT))
01562 break;
01563 if (a)
01564 print_with_symbols("\nCan't classify %y\n", name);
01565 #endif
01566 #else
01567 for (a = *rhs_top; a != NIL; a = a->next)
01568 a->support = UNKNOWN_SUPPORT;
01569 #endif
01570 } else {
01571
01572
01573
01574 for (a = *rhs_top; a != NIL; a = a->next)
01575 a->support = UNKNOWN_SUPPORT;
01576 }
01577
01578 allocate_with_pool(¤t_agent(production_pool), &p);
01579 p->name = name;
01580 if (name->sc.production) {
01581 print("Internal error: make_production called with name %s\n", name_of_production_being_reordered);
01582 print("for which a production already exists\n");
01583 }
01584 name->sc.production = p;
01585 p->documentation = NIL;
01586 p->filename = NIL;
01587 p->firing_count = 0;
01588 p->reference_count = 1;
01589 insert_at_head_of_dll(current_agent(all_productions_of_type)[type], p, next, prev);
01590 current_agent(num_productions_of_type)[type]++;
01591 p->type = type;
01592 p->declared_support = UNDECLARED_SUPPORT;
01593
01594 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
01595 p->trace_firings = FALSE;
01596 #endif
01597 p->p_node = NIL;
01598 p->action_list = *rhs_top;
01599 p->rhs_unbound_variables = NIL;
01600 p->instantiations = NIL;
01601 p->interrupt = FALSE;
01602
01603 return p;
01604 }
01605
01606 void deallocate_production(production * prod)
01607 {
01608 if (prod->instantiations) {
01609 char msg[MESSAGE_SIZE];
01610 strncpy(msg, "Internal error: deallocating prod. that still has inst's\n", MESSAGE_SIZE);
01611 msg[MESSAGE_SIZE - 1] = 0;
01612 abort_with_fatal_error(msg);
01613 }
01614 #ifdef WATCH_PRODUCTIONS
01615 print_with_symbols("DEALLOCATING PRODUCTION: %y\n", prod->name);
01616 #endif
01617 deallocate_action_list(prod->action_list);
01618
01619 deallocate_symbol_list_removing_references(prod->rhs_unbound_variables);
01620 symbol_remove_ref(prod->name);
01621 if (prod->documentation)
01622 free_memory_block_for_string(prod->documentation);
01623
01624 if (prod->filename)
01625 free_memory_block_for_string(prod->filename);
01626 free_with_pool(¤t_agent(production_pool), prod);
01627 }
01628
01629 void excise_production(production * prod, bool print_sharp_sign)
01630 {
01631
01632 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
01633 if (prod->trace_firings)
01634 remove_pwatch(prod);
01635 #endif
01636 #ifdef WATCH_PRODUCTIONS
01637 print_with_symbols("EXCISING PRODUCTION: %y\n", prod->name);
01638 print("Productions has reference count %d\n", prod->reference_count);
01639 #endif
01640
01641 remove_from_dll(current_agent(all_productions_of_type)[prod->type], prod, next, prev);
01642 current_agent(num_productions_of_type)[prod->type]--;
01643 if (print_sharp_sign)
01644 print("#");
01645 if (prod->p_node)
01646 excise_production_from_rete(prod);
01647 prod->name->sc.production = NIL;
01648 production_remove_ref(prod);
01649 }