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
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
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
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 #include "soarkernel.h"
00115 #include <ctype.h>
00116 #include "rete.h"
00117
00118
00119
00120
00121 bool discard_chunk_varnames = TRUE;
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 #ifdef TOKEN_SHARING_STATS
00149 #ifndef SHARING_FACTORS
00150 #define SHARING_FACTORS
00151 #endif
00152 #endif
00153
00154
00155 #ifdef NULL_ACTIVATION_STATS
00156 #ifndef DO_ACTIVATION_STATS_ON_REMOVALS
00157 #define DO_ACTIVATION_STATS_ON_REMOVALS
00158 #endif
00159 #endif
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 typedef struct alpha_mem_struct {
00179 struct alpha_mem_struct *next_in_hash_table;
00180 struct right_mem_struct *right_mems;
00181 struct rete_node_struct *beta_nodes;
00182 struct rete_node_struct *last_beta_node;
00183 Symbol *id;
00184 Symbol *attr;
00185 Symbol *value;
00186 bool acceptable;
00187 unsigned long am_id;
00188 unsigned long reference_count;
00189 unsigned long retesave_amindex;
00190 } alpha_mem;
00191
00192
00193 typedef struct right_mem_struct {
00194 wme *w;
00195 alpha_mem *am;
00196 struct right_mem_struct *next_in_bucket, *prev_in_bucket;
00197 struct right_mem_struct *next_in_am, *prev_in_am;
00198 struct right_mem_struct *next_from_wme, *prev_from_wme;
00199 } right_mem;
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 #define CONSTANT_RELATIONAL_RETE_TEST 0x00
00211 #define VARIABLE_RELATIONAL_RETE_TEST 0x10
00212 #define DISJUNCTION_RETE_TEST 0x20
00213 #define ID_IS_GOAL_RETE_TEST 0x30
00214 #define ID_IS_IMPASSE_RETE_TEST 0x31
00215 #define test_is_constant_relational_test(x) (((x) & 0xF0)==0x00)
00216 #define test_is_variable_relational_test(x) (((x) & 0xF0)==0x10)
00217
00218
00219
00220 #define RELATIONAL_EQUAL_RETE_TEST 0x00
00221 #define RELATIONAL_NOT_EQUAL_RETE_TEST 0x01
00222 #define RELATIONAL_LESS_RETE_TEST 0x02
00223 #define RELATIONAL_GREATER_RETE_TEST 0x03
00224 #define RELATIONAL_LESS_OR_EQUAL_RETE_TEST 0x04
00225 #define RELATIONAL_GREATER_OR_EQUAL_RETE_TEST 0x05
00226 #define RELATIONAL_SAME_TYPE_RETE_TEST 0x06
00227 #define kind_of_relational_test(x) ((x) & 0x0F)
00228 #define test_is_not_equal_test(x) (((x)==0x01) || ((x)==0x11))
00229
00230
00231 typedef unsigned short rete_node_level;
00232
00233 typedef struct var_location_struct {
00234 rete_node_level levels_up;
00235 byte field_num;
00236 } var_location;
00237
00238
00239 #define var_locations_equal(v1,v2) \
00240 ( ((v1).levels_up==(v2).levels_up) && ((v1).field_num==(v2).field_num) )
00241
00242
00243
00244
00245 #define field_from_wme(wme,field_num) \
00246 ( (&((wme)->id))[(field_num)] )
00247
00248
00249 typedef struct rete_test_struct {
00250 byte right_field_num;
00251 byte type;
00252 union rete_test_data_union {
00253 var_location variable_referent;
00254 Symbol *constant_referent;
00255 list *disjunction_list;
00256 } data;
00257 struct rete_test_struct *next;
00258 } rete_test;
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 #define UNHASHED_MEMORY_BNODE 0x02
00271 #define MEMORY_BNODE 0x03
00272 #define UNHASHED_MP_BNODE 0x06
00273 #define MP_BNODE 0x07
00274 #define UNHASHED_POSITIVE_BNODE 0x14
00275 #define POSITIVE_BNODE 0x15
00276 #define UNHASHED_NEGATIVE_BNODE 0x08
00277 #define NEGATIVE_BNODE 0x09
00278 #define DUMMY_TOP_BNODE 0x40
00279 #define DUMMY_MATCHES_BNODE 0x41
00280 #define CN_BNODE 0x42
00281 #define CN_PARTNER_BNODE 0x43
00282 #define P_BNODE 0x44
00283
00284 #define bnode_is_hashed(x) ((x) & 0x01)
00285 #define bnode_is_memory(x) ((x) & 0x02)
00286 #define bnode_is_positive(x) ((x) & 0x04)
00287 #define bnode_is_negative(x) ((x) & 0x08)
00288 #define bnode_is_posneg(x) ((x) & 0x0C)
00289 #define bnode_is_bottom_of_split_mp(x) ((x) & 0x10)
00290 #define real_parent_node(x) ( bnode_is_bottom_of_split_mp((x)->node_type) ? (x)->parent->parent : (x)->parent )
00291
00292 char *bnode_type_names[256];
00293
00294
00295 typedef struct pos_node_data_struct {
00296
00297 struct rete_node_struct *next_from_beta_mem, *prev_from_beta_mem;
00298 } pos_node_data;
00299
00300
00301 typedef struct posneg_node_data_struct {
00302 rete_test *other_tests;
00303 alpha_mem *alpha_mem;
00304 struct rete_node_struct *next_from_alpha_mem;
00305 struct rete_node_struct *prev_from_alpha_mem;
00306 struct rete_node_struct *nearest_ancestor_with_same_am;
00307 } posneg_node_data;
00308
00309
00310 typedef struct beta_memory_node_data_struct {
00311
00312 struct rete_node_struct *first_linked_child;
00313 } beta_memory_node_data;
00314
00315
00316 typedef struct cn_node_data_struct {
00317 struct rete_node_struct *partner;
00318 } cn_node_data;
00319
00320
00321 typedef struct p_node_data_struct {
00322 struct production_struct *prod;
00323 struct node_varnames_struct *parents_nvn;
00324 struct ms_change_struct *tentative_assertions;
00325 struct ms_change_struct *tentative_retractions;
00326 } p_node_data;
00327
00328 #define O_LIST 0
00329 #define I_LIST 1
00330
00331
00332 typedef struct non_pos_node_data_struct {
00333 struct token_struct *tokens;
00334 unsigned is_left_unlinked:1;
00335 } non_pos_node_data;
00336
00337
00338 typedef struct rete_node_struct {
00339 byte node_type;
00340
00341
00342
00343 byte left_hash_loc_field_num;
00344
00345 rete_node_level left_hash_loc_levels_up;
00346
00347 unsigned long node_id;
00348
00349 #ifdef SHARING_FACTORS
00350 unsigned long sharing_factor;
00351 #endif
00352
00353 struct rete_node_struct *parent;
00354 struct rete_node_struct *first_child;
00355 struct rete_node_struct *next_sibling;
00356 union rete_node_a_union {
00357 pos_node_data pos;
00358 non_pos_node_data np;
00359 } a;
00360 union rete_node_b_union {
00361 posneg_node_data posneg;
00362 beta_memory_node_data mem;
00363 cn_node_data cn;
00364 p_node_data p;
00365 } b;
00366 } rete_node;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 #define node_is_right_unlinked(node) \
00378 (((unsigned long)((node)->b.posneg.next_from_alpha_mem)) & 1)
00379
00380 #define mark_node_as_right_unlinked(node) { \
00381 (node)->b.posneg.next_from_alpha_mem = ((void *)1); }
00382
00383 #define relink_to_right_mem(node) { \
00384 rete_node *rtrm_ancestor, *rtrm_prev; \
00385 \
00386 rtrm_ancestor = (node)->b.posneg.nearest_ancestor_with_same_am; \
00387 while (rtrm_ancestor && node_is_right_unlinked(rtrm_ancestor)) \
00388 rtrm_ancestor = rtrm_ancestor->b.posneg.nearest_ancestor_with_same_am; \
00389 if (rtrm_ancestor) { \
00390 \
00391 rtrm_prev = rtrm_ancestor->b.posneg.prev_from_alpha_mem; \
00392 (node)->b.posneg.next_from_alpha_mem = rtrm_ancestor; \
00393 (node)->b.posneg.prev_from_alpha_mem = rtrm_prev; \
00394 rtrm_ancestor->b.posneg.prev_from_alpha_mem = (node); \
00395 if (rtrm_prev) rtrm_prev->b.posneg.next_from_alpha_mem = (node); \
00396 else (node)->b.posneg.alpha_mem->beta_nodes = (node); \
00397 } else { \
00398 \
00399 rtrm_prev = (node)->b.posneg.alpha_mem->last_beta_node; \
00400 (node)->b.posneg.next_from_alpha_mem = NIL; \
00401 (node)->b.posneg.prev_from_alpha_mem = rtrm_prev; \
00402 (node)->b.posneg.alpha_mem->last_beta_node = (node); \
00403 if (rtrm_prev) rtrm_prev->b.posneg.next_from_alpha_mem = (node); \
00404 else (node)->b.posneg.alpha_mem->beta_nodes = (node); \
00405 } }
00406
00407 #define unlink_from_right_mem(node) { \
00408 if ((node)->b.posneg.next_from_alpha_mem == NIL) \
00409 (node)->b.posneg.alpha_mem->last_beta_node = \
00410 (node)->b.posneg.prev_from_alpha_mem; \
00411 remove_from_dll ((node)->b.posneg.alpha_mem->beta_nodes, (node), \
00412 b.posneg.next_from_alpha_mem, \
00413 b.posneg.prev_from_alpha_mem); \
00414 mark_node_as_right_unlinked (node); }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 #define node_is_left_unlinked(node) \
00426 (((unsigned long)((node)->a.pos.next_from_beta_mem)) & 1)
00427
00428 #define mark_node_as_left_unlinked(node) { \
00429 (node)->a.pos.next_from_beta_mem = ((void *)1); }
00430
00431 #define relink_to_left_mem(node) { \
00432 insert_at_head_of_dll ((node)->parent->b.mem.first_linked_child, (node), \
00433 a.pos.next_from_beta_mem, \
00434 a.pos.prev_from_beta_mem); }
00435
00436 #define unlink_from_left_mem(node) { \
00437 remove_from_dll ((node)->parent->b.mem.first_linked_child, (node), \
00438 a.pos.next_from_beta_mem, \
00439 a.pos.prev_from_beta_mem); \
00440 mark_node_as_left_unlinked(node); }
00441
00442
00443
00444
00445 #define make_mp_bnode_left_unlinked(node) {(node)->a.np.is_left_unlinked = 1;}
00446 #define make_mp_bnode_left_linked(node) {(node)->a.np.is_left_unlinked = 0;}
00447 #define mp_bnode_is_left_unlinked(node) ((node)->a.np.is_left_unlinked)
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 #define new_left_token(new,current_node,parent_tok,parent_wme) { \
00459 (new)->node = (current_node); \
00460 insert_at_head_of_dll ((current_node)->a.np.tokens, (new), \
00461 next_of_node, prev_of_node); \
00462 (new)->first_child = NIL; \
00463 (new)->parent = (parent_tok); \
00464 insert_at_head_of_dll ((parent_tok)->first_child, (new), \
00465 next_sibling, prev_sibling); \
00466 (new)->w = (parent_wme); \
00467 if (parent_wme) insert_at_head_of_dll ((parent_wme)->tokens, (new), \
00468 next_from_wme, prev_from_wme); }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 #ifdef _WINDOWS
00483 #define LOG2_LEFT_HT_SIZE 13
00484 #define LOG2_RIGHT_HT_SIZE 13
00485 #else
00486 #define LOG2_LEFT_HT_SIZE 14
00487 #define LOG2_RIGHT_HT_SIZE 14
00488 #endif
00489
00490 #define LEFT_HT_SIZE (((long) 1) << LOG2_LEFT_HT_SIZE)
00491 #define RIGHT_HT_SIZE (((long) 1) << LOG2_RIGHT_HT_SIZE)
00492
00493 #define LEFT_HT_MASK (LEFT_HT_SIZE - 1)
00494 #define RIGHT_HT_MASK (RIGHT_HT_SIZE - 1)
00495
00496
00497 #define left_ht_bucket(hv) \
00498 (* ( ((token **) current_agent(left_ht)) + ((hv) & LEFT_HT_MASK)))
00499 #define right_ht_bucket(hv) \
00500 (* ( ((right_mem **) current_agent(right_ht)) + ((hv) & RIGHT_HT_MASK)))
00501
00502 #define insert_token_into_left_ht(tok,hv) { \
00503 token **header_zy37; \
00504 header_zy37 = ((token **) current_agent(left_ht)) + ((hv) & LEFT_HT_MASK); \
00505 insert_at_head_of_dll (*header_zy37, (tok), \
00506 a.ht.next_in_bucket, a.ht.prev_in_bucket); }
00507
00508 #define remove_token_from_left_ht(tok,hv) { \
00509 fast_remove_from_dll (left_ht_bucket(hv), tok, token, \
00510 a.ht.next_in_bucket, a.ht.prev_in_bucket); }
00511
00512
00513
00514
00515
00516
00517
00518 void (*(left_addition_routines[256])) (rete_node * node, token * tok, wme * w);
00519 void (*(right_addition_routines[256])) (rete_node * node, wme * w);
00520 void remove_token_and_subtree(token * tok);
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 #define activation_entry_sanity_check() {}
00531 #define activation_exit_sanity_check() {}
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 rete_node *node_to_ignore_for_activation_stats = NIL;
00547
00548 #ifdef NULL_ACTIVATION_STATS
00549
00550 void null_activation_stats_for_right_activation(rete_node * node)
00551 {
00552 if (node == node_to_ignore_for_activation_stats)
00553 return;
00554 switch (node->node_type) {
00555 case POSITIVE_BNODE:
00556 case UNHASHED_POSITIVE_BNODE:
00557 current_agent(num_right_activations)++;
00558 if (!node->parent->a.np.tokens)
00559 current_agent(num_null_right_activations)++;
00560 break;
00561 case MP_BNODE:
00562 case UNHASHED_MP_BNODE:
00563 current_agent(num_right_activations)++;
00564 if (!node->a.np.tokens)
00565 current_agent(num_null_right_activations)++;
00566 break;
00567 }
00568 }
00569
00570 void null_activation_stats_for_left_activation(rete_node * node)
00571 {
00572 switch (node->node_type) {
00573 case POSITIVE_BNODE:
00574 case UNHASHED_POSITIVE_BNODE:
00575 current_agent(num_left_activations)++;
00576 if (node->b.posneg.alpha_mem->right_mems == NIL)
00577 current_agent(num_null_left_activations)++;
00578 break;
00579 case MP_BNODE:
00580 case UNHASHED_MP_BNODE:
00581 if (mp_bnode_is_left_unlinked(node))
00582 return;
00583 current_agent(num_left_activations)++;
00584 if (node->b.posneg.alpha_mem->right_mems == NIL)
00585 current_agent(num_null_left_activations)++;
00586 break;
00587 }
00588 }
00589
00590 void print_null_activation_stats()
00591 {
00592 print("\nActivations: %lu right (%lu null), %lu left (%lu null)\n",
00593 current_agent(num_right_activations),
00594 current_agent(num_null_right_activations),
00595 current_agent(num_left_activations), current_agent(num_null_left_activations));
00596 }
00597
00598 #else
00599
00600 #define null_activation_stats_for_right_activation(node) {}
00601 #define null_activation_stats_for_left_activation(node) {}
00602 #define print_null_activation_stats() {}
00603
00604 #endif
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 #ifdef SHARING_FACTORS
00624
00625 #define init_sharing_stats_for_new_node(node) { (node)->sharing_factor = 0; }
00626
00627 #define set_sharing_factor(node,sf) { \
00628 long ssf_237; \
00629 ssf_237 = (sf) - ((node)->sharing_factor); \
00630 (node)->sharing_factor = (sf); \
00631 current_agent(rete_node_counts_if_no_sharing)[(node)->node_type]+=ssf_237; }
00632
00633
00634 void adjust_sharing_factors_from_here_to_top(rete_node * node, int delta)
00635 {
00636 while (node != NIL) {
00637 current_agent(rete_node_counts_if_no_sharing)[node->node_type] += delta;
00638 node->sharing_factor += delta;
00639 if (node->node_type == CN_BNODE)
00640 node = node->b.cn.partner;
00641 else
00642 node = node->parent;
00643 }
00644 }
00645
00646 #else
00647
00648 #define init_sharing_stats_for_new_node(node) {}
00649 #define set_sharing_factor(node,sf) {}
00650 #define adjust_sharing_factors_from_here_to_top(node,delta) {}
00651
00652 #endif
00653
00654
00655
00656
00657
00658
00659
00660 #ifdef TOKEN_SHARING_STATS
00661
00662
00663
00664 #define real_sharing_factor(node) \
00665 ((node)->sharing_factor ? (node)->sharing_factor : 1)
00666
00667 #define token_added(node) { \
00668 current_agent(token_additions)++; \
00669 current_agent(token_additions_without_sharing) += real_sharing_factor(node);}
00670
00671 #else
00672
00673 #define token_added(node) {}
00674
00675 #endif
00676
00677
00678
00679 #define right_node_activation(node,add) { \
00680 null_activation_stats_for_right_activation(node); }
00681
00682
00683
00684 #define left_node_activation(node,add) { \
00685 null_activation_stats_for_left_activation(node); }
00686
00687
00688
00689 #define init_new_rete_node_with_type(node,type) { \
00690 (node)->node_type = (type); \
00691 current_agent(rete_node_counts)[(type)]++; \
00692 init_sharing_stats_for_new_node(node); }
00693
00694 #define update_stats_for_destroying_node(node) { \
00695 set_sharing_factor(node,0); \
00696 current_agent(rete_node_counts)[(node)->node_type]--; }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 Symbol *find_goal_for_match_set_change_assertion(ms_change * msc)
00725 {
00726
00727 wme *lowest_goal_wme;
00728 goal_stack_level lowest_level_so_far;
00729 token *tok;
00730
00731 #ifdef DEBUG_WATERFALL
00732 print_with_symbols("\nMatch goal for assertion: %y", msc->p_node->b.p.prod->name);
00733 #endif
00734
00735 lowest_goal_wme = NIL;
00736 lowest_level_so_far = -1;
00737
00738 if (msc->w) {
00739 if (msc->w->id->id.isa_goal == TRUE) {
00740 lowest_goal_wme = msc->w;
00741 lowest_level_so_far = msc->w->id->id.level;
00742 }
00743 }
00744
00745 for (tok = msc->tok; tok != current_agent(dummy_top_token); tok = tok->parent) {
00746 if (tok->w != NIL) {
00747
00748 if (tok->w->id->id.isa_goal == TRUE) {
00749
00750 if (lowest_goal_wme == NIL)
00751 lowest_goal_wme = tok->w;
00752
00753 else {
00754 if (tok->w->id->id.level > lowest_goal_wme->id->id.level)
00755 lowest_goal_wme = tok->w;
00756 }
00757 }
00758
00759 }
00760 }
00761
00762 if (lowest_goal_wme) {
00763 #ifdef DEBUG_WATERFALL
00764 print_with_symbols(" is [%y]", lowest_goal_wme->id);
00765 #endif
00766 return lowest_goal_wme->id;
00767 }
00768 {
00769 char msg[MESSAGE_SIZE];
00770 print_with_symbols("\nError: Did not find goal for ms_change assertion: %y\n", msc->p_node->b.p.prod->name);
00771 snprintf(msg, MESSAGE_SIZE, "\nError: Did not find goal for ms_change assertion: %s\n",
00772 symbol_to_string(msc->p_node->b.p.prod->name, TRUE, NIL, 0));
00773 msg[MESSAGE_SIZE - 1] = 0;
00774 abort_with_fatal_error(msg);
00775 }
00776 return 0;
00777 }
00778
00779 Symbol *find_goal_for_match_set_change_retraction(ms_change * msc)
00780 {
00781
00782 #ifdef DEBUG_WATERFALL
00783 print_with_symbols("\nMatch goal level for retraction: %y", msc->inst->prod->name);
00784 #endif
00785
00786 if (msc->inst->match_goal) {
00787
00788 #ifdef DEBUG_WATERFALL
00789 print_with_symbols(" is [%y]", msc->inst->match_goal);
00790 #endif
00791 return msc->inst->match_goal;
00792
00793 } else {
00794
00795 #ifdef DEBUG_WATERFALL
00796 print(" is NIL (nil goal retraction)");
00797 #endif
00798 return NIL;
00799
00800 }
00801 }
00802
00803 void print_assertion(ms_change * msc)
00804 {
00805
00806 if (msc->p_node)
00807 print_with_symbols("\nAssertion: %y", msc->p_node->b.p.prod->name);
00808 else
00809 print("\nAssertion exists but has no p_node");
00810 }
00811
00812 void print_retraction(ms_change * msc)
00813 {
00814
00815 if (msc->p_node)
00816 print_with_symbols("\nRetraction: %y", msc->p_node->b.p.prod->name);
00817 else
00818 print("\nRetraction exists but has no p_node");
00819 }
00820
00821
00822
00823 bool any_assertions_or_retractions_ready(void)
00824 {
00825
00826 Symbol *goal;
00827
00828
00829 #ifndef SOAR_8_ONLY
00830 if (current_agent(operand2_mode) == TRUE) {
00831 #endif
00832
00833
00834
00835
00836 if (current_agent(nil_goal_retractions))
00837 return TRUE;
00838
00839
00840
00841
00842 for (goal = current_agent(bottom_goal); goal; goal = goal->id.higher_goal) {
00843
00844
00845 if (goal->id.ms_o_assertions || goal->id.ms_i_assertions || goal->id.ms_retractions)
00846 return TRUE;
00847 }
00848
00849
00850
00851
00852
00853 return FALSE;
00854 #ifndef SOAR_8_ONLY
00855 }
00856
00857
00858
00859 else
00860
00861 return (bool) (current_agent(ms_assertions) || current_agent(ms_retractions));
00862 #endif
00863
00864 }
00865
00866
00867
00868 bool any_i_assertions_or_retractions_ready(void)
00869 {
00870 return (bool) (current_agent(ms_i_assertions) || current_agent(ms_retractions));
00871 }
00872
00873
00874
00875 bool get_next_assertion(production ** prod, struct token_struct ** tok, wme ** w)
00876 {
00877 ms_change *msc;
00878
00879 msc = NIL;
00880
00881
00882 #ifndef SOAR_8_ONLY
00883 if (current_agent(operand2_mode) == TRUE) {
00884 #endif
00885
00886
00887
00888
00889
00890
00891 if (current_agent(active_goal)) {
00892 if (current_agent(FIRING_TYPE) == PE_PRODS) {
00893 if (!current_agent(active_goal)->id.ms_o_assertions)
00894 return FALSE;
00895
00896 msc = current_agent(active_goal)->id.ms_o_assertions;
00897 remove_from_dll(current_agent(ms_o_assertions), msc, next, prev);
00898 remove_from_dll(current_agent(active_goal)->id.ms_o_assertions, msc, next_in_level, prev_in_level);
00899
00900 } else {
00901
00902 if (!current_agent(active_goal)->id.ms_i_assertions)
00903 return FALSE;
00904
00905 msc = current_agent(active_goal)->id.ms_i_assertions;
00906 remove_from_dll(current_agent(ms_i_assertions), msc, next, prev);
00907 remove_from_dll(current_agent(active_goal)->id.ms_i_assertions, msc, next_in_level, prev_in_level);
00908 }
00909
00910 } else {
00911
00912
00913
00914
00915
00916
00917
00918
00919 if (((current_agent(FIRING_TYPE) == PE_PRODS) && current_agent(ms_o_assertions))
00920 || ((current_agent(FIRING_TYPE) == IE_PRODS) && current_agent(ms_i_assertions))) {
00921
00922 char msg[MESSAGE_SIZE];
00923 strncpy(msg, "\nrete.c: Error: No active goal, but assertions are on the assertion list.",
00924 MESSAGE_SIZE);
00925 msg[MESSAGE_SIZE - 1] = 0;
00926 abort_with_fatal_error(msg);
00927
00928 }
00929
00930 return FALSE;
00931
00932
00933
00934 }
00935
00936 #ifndef SOAR_8_ONLY
00937 }
00938
00939
00940 else {
00941 if (!current_agent(ms_assertions))
00942 return FALSE;
00943 msc = current_agent(ms_assertions);
00944
00945 remove_from_dll(current_agent(ms_assertions), msc, next, prev);
00946 }
00947 #endif
00948
00949 remove_from_dll(msc->p_node->b.p.tentative_assertions, msc, next_of_node, prev_of_node);
00950 *prod = msc->p_node->b.p.prod;
00951 *tok = msc->tok;
00952 *w = msc->w;
00953 free_with_pool(¤t_agent(ms_change_pool), msc);
00954 return TRUE;
00955 }
00956
00957 bool get_next_retraction(instantiation ** inst)
00958 {
00959 ms_change *msc;
00960
00961
00962 #ifndef SOAR_8_ONLY
00963 if (!current_agent(operand2_mode)) {
00964
00965
00966 if (!current_agent(ms_retractions))
00967 return FALSE;
00968 msc = current_agent(ms_retractions);
00969 remove_from_dll(current_agent(ms_retractions), msc, next, prev);
00970 if (msc->p_node)
00971 remove_from_dll(msc->p_node->b.p.tentative_retractions, msc, next_of_node, prev_of_node);
00972 *inst = msc->inst;
00973 free_with_pool(¤t_agent(ms_change_pool), msc);
00974 return TRUE;
00975
00976
00977 } else {
00978 #endif
00979
00980
00981
00982 if (current_agent(active_level) == 0)
00983 return FALSE;
00984
00985 if (!current_agent(active_goal)->id.ms_retractions)
00986 return FALSE;
00987
00988 msc = current_agent(active_goal)->id.ms_retractions;
00989
00990
00991 remove_from_dll(current_agent(ms_retractions), msc, next, prev);
00992
00993 remove_from_dll(current_agent(active_goal)->id.ms_retractions, msc, next_in_level, prev_in_level);
00994 if (msc->p_node)
00995 remove_from_dll(msc->p_node->b.p.tentative_retractions, msc, next_of_node, prev_of_node);
00996 *inst = msc->inst;
00997 free_with_pool(¤t_agent(ms_change_pool), msc);
00998 return TRUE;
00999
01000 #ifndef SOAR_8_ONLY
01001 }
01002 #endif
01003
01004 }
01005
01006
01007
01008
01009
01010
01011
01012
01013 bool get_next_nil_goal_retraction(instantiation ** inst)
01014 {
01015 ms_change *msc;
01016
01017 if (!current_agent(nil_goal_retractions))
01018 return FALSE;
01019 msc = current_agent(nil_goal_retractions);
01020
01021
01022 remove_from_dll(current_agent(nil_goal_retractions), msc, next_in_level, prev_in_level);
01023
01024
01025
01026
01027 remove_from_dll(current_agent(ms_retractions), msc, next, prev);
01028
01029 if (msc->p_node) {
01030 remove_from_dll(msc->p_node->b.p.tentative_retractions, msc, next_of_node, prev_of_node);
01031 }
01032 *inst = msc->inst;
01033 free_with_pool(¤t_agent(ms_change_pool), msc);
01034 return TRUE;
01035
01036 }
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 #define wme_matches_alpha_mem(w,am) ( \
01066 (((am)->id==NIL) || ((am)->id==(w)->id)) && \
01067 (((am)->attr==NIL) || ((am)->attr==(w)->attr)) && \
01068 (((am)->value==NIL) || ((am)->value==(w)->value)) && \
01069 ((am)->acceptable==(w)->acceptable))
01070
01071
01072 #define alpha_hash_value(i,a,v,num_bits) \
01073 ( ( ((i) ? ((Symbol *)(i))->common.hash_id : 0) ^ \
01074 ((a) ? ((Symbol *)(a))->common.hash_id : 0) ^ \
01075 ((v) ? ((Symbol *)(v))->common.hash_id : 0) ) & \
01076 masks_for_n_low_order_bits[(num_bits)] )
01077
01078
01079 unsigned long hash_alpha_mem(void *item, short num_bits)
01080 {
01081 alpha_mem *am;
01082
01083 am = item;
01084 return alpha_hash_value(am->id, am->attr, am->value, num_bits);
01085 }
01086
01087
01088 #define table_for_tests(id,attr,value,acceptable) \
01089 current_agent(alpha_hash_tables) [ ((id) ? 1 : 0) + ((attr) ? 2 : 0) + \
01090 ((value) ? 4 : 0) + \
01091 ((acceptable) ? 8 : 0) ]
01092
01093 #define get_next_alpha_mem_id() (current_agent(alpha_mem_id_counter)++)
01094
01095
01096
01097 void add_wme_to_alpha_mem(wme * w, alpha_mem * am)
01098 {
01099 right_mem **header, *rm;
01100 unsigned long hv;
01101
01102
01103 allocate_with_pool(¤t_agent(right_mem_pool), &rm);
01104 rm->w = w;
01105 rm->am = am;
01106
01107
01108 hv = am->am_id ^ w->id->common.hash_id;
01109 header = ((right_mem **) current_agent(right_ht)) + (hv & RIGHT_HT_MASK);
01110 insert_at_head_of_dll(*header, rm, next_in_bucket, prev_in_bucket);
01111 insert_at_head_of_dll(am->right_mems, rm, next_in_am, prev_in_am);
01112 insert_at_head_of_dll(w->right_mems, rm, next_from_wme, prev_from_wme);
01113 }
01114
01115
01116
01117 void remove_wme_from_alpha_mem(right_mem * rm)
01118 {
01119 wme *w;
01120 alpha_mem *am;
01121 unsigned long hv;
01122 right_mem **header;
01123
01124 w = rm->w;
01125 am = rm->am;
01126
01127
01128 hv = am->am_id ^ w->id->common.hash_id;
01129 header = ((right_mem **) current_agent(right_ht)) + (hv & RIGHT_HT_MASK);
01130 remove_from_dll(*header, rm, next_in_bucket, prev_in_bucket);
01131 remove_from_dll(am->right_mems, rm, next_in_am, prev_in_am);
01132 remove_from_dll(w->right_mems, rm, next_from_wme, prev_from_wme);
01133
01134
01135 free_with_pool(¤t_agent(right_mem_pool), rm);
01136 }
01137
01138
01139 alpha_mem *find_alpha_mem(Symbol * id, Symbol * attr, Symbol * value, bool acceptable)
01140 {
01141 hash_table *ht;
01142 alpha_mem *am;
01143 unsigned long hash_value;
01144
01145 ht = table_for_tests(id, attr, value, acceptable);
01146 hash_value = alpha_hash_value(id, attr, value, ht->log2size);
01147
01148 for (am = (alpha_mem *) (*(ht->buckets + hash_value)); am != NIL; am = am->next_in_hash_table)
01149 if ((am->id == id) && (am->attr == attr) && (am->value == value) && (am->acceptable == acceptable))
01150 return am;
01151 return NIL;
01152 }
01153
01154
01155
01156 alpha_mem *find_or_make_alpha_mem(Symbol * id, Symbol * attr, Symbol * value, bool acceptable)
01157 {
01158 hash_table *ht;
01159 alpha_mem *am, *more_general_am;
01160 wme *w;
01161 right_mem *rm;
01162
01163
01164 am = find_alpha_mem(id, attr, value, acceptable);
01165 if (am) {
01166 am->reference_count++;
01167 return am;
01168 }
01169
01170
01171 allocate_with_pool(¤t_agent(alpha_mem_pool), &am);
01172 am->next_in_hash_table = NIL;
01173 am->right_mems = NIL;
01174 am->beta_nodes = NIL;
01175 am->last_beta_node = NIL;
01176 am->reference_count = 1;
01177 am->id = id;
01178 if (id)
01179 symbol_add_ref(id);
01180 am->attr = attr;
01181 if (attr)
01182 symbol_add_ref(attr);
01183 am->value = value;
01184 if (value)
01185 symbol_add_ref(value);
01186 am->acceptable = acceptable;
01187 am->am_id = get_next_alpha_mem_id();
01188 ht = table_for_tests(id, attr, value, acceptable);
01189 add_to_hash_table(ht, am);
01190
01191
01192 more_general_am = NIL;
01193 if (id)
01194 more_general_am = find_alpha_mem(NIL, attr, value, acceptable);
01195 if (!more_general_am && value)
01196 more_general_am = find_alpha_mem(NIL, attr, NIL, acceptable);
01197 if (more_general_am) {
01198
01199 for (rm = more_general_am->right_mems; rm != NIL; rm = rm->next_in_am)
01200 if (wme_matches_alpha_mem(rm->w, am))
01201 add_wme_to_alpha_mem(rm->w, am);
01202 } else {
01203
01204 for (w = current_agent(all_wmes_in_rete); w != NIL; w = w->rete_next)
01205 if (wme_matches_alpha_mem(w, am))
01206 add_wme_to_alpha_mem(w, am);
01207 }
01208
01209 return am;
01210 }
01211
01212
01213
01214
01215 void add_wme_to_aht(hash_table * ht, unsigned long hash_value, wme * w)
01216 {
01217 alpha_mem *am;
01218 rete_node *node, *next;
01219
01220 hash_value = hash_value & masks_for_n_low_order_bits[ht->log2size];
01221 am = (alpha_mem *) (*(ht->buckets + hash_value));
01222 while (am != NIL) {
01223 if (wme_matches_alpha_mem(w, am)) {
01224
01225 add_wme_to_alpha_mem(w, am);
01226
01227
01228 for (node = am->beta_nodes; node != NIL; node = next) {
01229 next = node->b.posneg.next_from_alpha_mem;
01230 (*(right_addition_routines[node->node_type])) (node, w);
01231 }
01232 return;
01233 }
01234 am = am->next_in_hash_table;
01235 }
01236 }
01237
01238 #define xor(i,a,v) ((i) ^ (a) ^ (v))
01239
01240
01241 void add_wme_to_rete(wme * w)
01242 {
01243 unsigned long hi, ha, hv;
01244
01245
01246 insert_at_head_of_dll(current_agent(all_wmes_in_rete), w, rete_next, rete_prev);
01247 current_agent(num_wmes_in_rete)++;
01248
01249
01250 w->right_mems = NIL;
01251 w->tokens = NIL;
01252
01253
01254 hi = w->id->common.hash_id;
01255 ha = w->attr->common.hash_id;
01256 hv = w->value->common.hash_id;
01257
01258 if (w->acceptable) {
01259 add_wme_to_aht(current_agent(alpha_hash_tables)[8], xor(0, 0, 0), w);
01260 add_wme_to_aht(current_agent(alpha_hash_tables)[9], xor(hi, 0, 0), w);
01261 add_wme_to_aht(current_agent(alpha_hash_tables)[10], xor(0, ha, 0), w);
01262 add_wme_to_aht(current_agent(alpha_hash_tables)[11], xor(hi, ha, 0), w);
01263 add_wme_to_aht(current_agent(alpha_hash_tables)[12], xor(0, 0, hv), w);
01264 add_wme_to_aht(current_agent(alpha_hash_tables)[13], xor(hi, 0, hv), w);
01265 add_wme_to_aht(current_agent(alpha_hash_tables)[14], xor(0, ha, hv), w);
01266 add_wme_to_aht(current_agent(alpha_hash_tables)[15], xor(hi, ha, hv), w);
01267 } else {
01268 add_wme_to_aht(current_agent(alpha_hash_tables)[0], xor(0, 0, 0), w);
01269 add_wme_to_aht(current_agent(alpha_hash_tables)[1], xor(hi, 0, 0), w);
01270 add_wme_to_aht(current_agent(alpha_hash_tables)[2], xor(0, ha, 0), w);
01271 add_wme_to_aht(current_agent(alpha_hash_tables)[3], xor(hi, ha, 0), w);
01272 add_wme_to_aht(current_agent(alpha_hash_tables)[4], xor(0, 0, hv), w);
01273 add_wme_to_aht(current_agent(alpha_hash_tables)[5], xor(hi, 0, hv), w);
01274 add_wme_to_aht(current_agent(alpha_hash_tables)[6], xor(0, ha, hv), w);
01275 add_wme_to_aht(current_agent(alpha_hash_tables)[7], xor(hi, ha, hv), w);
01276 }
01277 }
01278
01279
01280 void remove_wme_from_rete(wme * w)
01281 {
01282 right_mem *rm;
01283 alpha_mem *am;
01284 rete_node *node, *next, *child;
01285 token *tok, *left;
01286
01287
01288 remove_from_dll(current_agent(all_wmes_in_rete), w, rete_next, rete_prev);
01289 current_agent(num_wmes_in_rete)--;
01290
01291
01292 while (w->right_mems) {
01293 rm = w->right_mems;
01294 am = rm->am;
01295
01296 remove_wme_from_alpha_mem(rm);
01297
01298 #ifdef DO_ACTIVATION_STATS_ON_REMOVALS
01299
01300 for (node = am->beta_nodes; node != NIL; node = next) {
01301 next = node->b.posneg.next_from_alpha_mem;
01302 right_node_activation(node, FALSE);
01303 }
01304 #endif
01305
01306
01307
01308 if (am->right_mems == NIL) {
01309 for (node = am->beta_nodes; node != NIL; node = next) {
01310 next = node->b.posneg.next_from_alpha_mem;
01311 switch (node->node_type) {
01312 case POSITIVE_BNODE:
01313 case UNHASHED_POSITIVE_BNODE:
01314 unlink_from_left_mem(node);
01315 break;
01316 case MP_BNODE:
01317 case UNHASHED_MP_BNODE:
01318 make_mp_bnode_left_unlinked(node);
01319 break;
01320 }
01321 }
01322 }
01323 }
01324
01325
01326 while (w->tokens) {
01327 tok = w->tokens;
01328 node = tok->node;
01329 if (!tok->parent) {
01330
01331 left = tok->a.neg.left_token;
01332 remove_from_dll(w->tokens, tok, next_from_wme, prev_from_wme);
01333 remove_from_dll(left->negrm_tokens, tok, a.neg.next_negrm, a.neg.prev_negrm);
01334 free_with_pool(¤t_agent(token_pool), tok);
01335 if (!left->negrm_tokens) {
01336 for (child = node->first_child; child != NIL; child = child->next_sibling)
01337 (*(left_addition_routines[child->node_type])) (child, left, NIL);
01338 }
01339 } else {
01340 remove_token_and_subtree(w->tokens);
01341 }
01342 }
01343 }
01344
01345
01346 void remove_ref_to_alpha_mem(alpha_mem * am)
01347 {
01348 hash_table *ht;
01349
01350 am->reference_count--;
01351 if (am->reference_count != 0)
01352 return;
01353
01354 ht = table_for_tests(am->id, am->attr, am->value, am->acceptable);
01355 remove_from_hash_table(ht, am);
01356 if (am->id)
01357 symbol_remove_ref(am->id);
01358 if (am->attr)
01359 symbol_remove_ref(am->attr);
01360 if (am->value)
01361 symbol_remove_ref(am->value);
01362 while (am->right_mems)
01363 remove_wme_from_alpha_mem(am->right_mems);
01364 free_with_pool(¤t_agent(alpha_mem_pool), am);
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380 #define get_next_beta_node_id() (current_agent(beta_node_id_counter)++)
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 void init_dummy_top_node()
01391 {
01392
01393 allocate_with_pool(¤t_agent(rete_node_pool), ¤t_agent(dummy_top_node));
01394 init_new_rete_node_with_type(current_agent(dummy_top_node), DUMMY_TOP_BNODE);
01395 current_agent(dummy_top_node)->parent = NIL;
01396 current_agent(dummy_top_node)->first_child = NIL;
01397 current_agent(dummy_top_node)->next_sibling = NIL;
01398
01399
01400 allocate_with_pool(¤t_agent(token_pool), ¤t_agent(dummy_top_token));
01401 current_agent(dummy_top_token)->parent = NIL;
01402 current_agent(dummy_top_token)->node = current_agent(dummy_top_node);
01403 current_agent(dummy_top_token)->w = NIL;
01404 current_agent(dummy_top_token)->first_child = NIL;
01405 current_agent(dummy_top_token)->next_sibling = NIL;
01406 current_agent(dummy_top_token)->prev_sibling = NIL;
01407 current_agent(dummy_top_token)->next_from_wme = NIL;
01408 current_agent(dummy_top_token)->prev_from_wme = NIL;
01409 current_agent(dummy_top_token)->next_of_node = NIL;
01410 current_agent(dummy_top_token)->prev_of_node = NIL;
01411 current_agent(dummy_top_node)->a.np.tokens = current_agent(dummy_top_token);
01412 }
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422 void remove_node_from_parents_list_of_children(rete_node * node)
01423 {
01424 rete_node *prev_sibling;
01425
01426 prev_sibling = node->parent->first_child;
01427 if (prev_sibling == node) {
01428 node->parent->first_child = node->next_sibling;
01429 return;
01430 }
01431 while (prev_sibling->next_sibling != node)
01432 prev_sibling = prev_sibling->next_sibling;
01433 prev_sibling->next_sibling = node->next_sibling;
01434 }
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444 void update_node_with_matches_from_above(rete_node * child)
01445 {
01446 rete_node *parent;
01447 rete_node *saved_parents_first_child, *saved_childs_next_sibling;
01448 right_mem *rm;
01449 token *tok;
01450
01451 if (bnode_is_bottom_of_split_mp(child->node_type)) {
01452 char msg[MESSAGE_SIZE];
01453 strncpy(msg, "\nrete.c: Internal error: update_node_with_matches_from_above called on split node",
01454 MESSAGE_SIZE);
01455 msg[MESSAGE_SIZE - 1] = 0;
01456 abort_with_fatal_error(msg);
01457 }
01458
01459 parent = child->parent;
01460
01461
01462 if (parent->node_type == DUMMY_TOP_BNODE) {
01463 (*(left_addition_routines[child->node_type])) (child, current_agent(dummy_top_token), NIL);
01464 return;
01465 }
01466
01467
01468
01469
01470
01471 if (bnode_is_positive(parent->node_type)) {
01472
01473
01474
01475 if (node_is_right_unlinked(parent))
01476 return;
01477 saved_parents_first_child = parent->first_child;
01478 saved_childs_next_sibling = child->next_sibling;
01479 parent->first_child = child;
01480 child->next_sibling = NIL;
01481
01482 node_to_ignore_for_activation_stats = parent;
01483 for (rm = parent->b.posneg.alpha_mem->right_mems; rm != NIL; rm = rm->next_in_am)
01484 (*(right_addition_routines[parent->node_type])) (parent, rm->w);
01485 node_to_ignore_for_activation_stats = NIL;
01486 parent->first_child = saved_parents_first_child;
01487 child->next_sibling = saved_childs_next_sibling;
01488 return;
01489 }
01490
01491
01492
01493 for (tok = parent->a.np.tokens; tok != NIL; tok = tok->next_of_node)
01494 if (!tok->negrm_tokens)
01495 (*(left_addition_routines[child->node_type])) (child, tok, NIL);
01496 }
01497
01498
01499
01500
01501
01502
01503
01504
01505 rete_node *nearest_ancestor_with_same_am(rete_node * node, alpha_mem * am)
01506 {
01507 while (node->node_type != DUMMY_TOP_BNODE) {
01508 if (node->node_type == CN_BNODE)
01509 node = node->b.cn.partner->parent;
01510 else
01511 node = real_parent_node(node);
01512 if (bnode_is_posneg(node->node_type) && (node->b.posneg.alpha_mem == am))
01513 return node;
01514 }
01515 return NIL;
01516 }
01517
01518
01519
01520
01521
01522
01523
01524 rete_node *make_new_mem_node(rete_node * parent, byte node_type, var_location left_hash_loc)
01525 {
01526 rete_node *node;
01527
01528
01529 allocate_with_pool(¤t_agent(rete_node_pool), &node);
01530 init_new_rete_node_with_type(node, node_type);
01531 node->parent = parent;
01532 node->next_sibling = parent->first_child;
01533 parent->first_child = node;
01534 node->first_child = NIL;
01535 node->b.mem.first_linked_child = NIL;
01536 node->left_hash_loc_field_num = left_hash_loc.field_num;
01537 node->left_hash_loc_levels_up = left_hash_loc.levels_up;
01538 node->node_id = get_next_beta_node_id();
01539 node->a.np.tokens = NIL;
01540
01541
01542 update_node_with_matches_from_above(node);
01543
01544 return node;
01545 }
01546
01547
01548
01549
01550
01551
01552
01553 rete_node *make_new_positive_node(rete_node * parent_mem, byte node_type,
01554 alpha_mem * am, rete_test * rt, bool prefer_left_unlinking)
01555 {
01556 rete_node *node;
01557
01558
01559 allocate_with_pool(¤t_agent(rete_node_pool), &node);
01560 init_new_rete_node_with_type(node, node_type);
01561 node->parent = parent_mem;
01562 node->next_sibling = parent_mem->first_child;
01563 parent_mem->first_child = node;
01564 node->first_child = NIL;
01565 relink_to_left_mem(node);
01566 node->b.posneg.other_tests = rt;
01567 node->b.posneg.alpha_mem = am;
01568 node->b.posneg.nearest_ancestor_with_same_am = nearest_ancestor_with_same_am(node, am);
01569 relink_to_right_mem(node);
01570
01571
01572
01573
01574
01575 if (!parent_mem->a.np.tokens)
01576 unlink_from_right_mem(node);
01577 if ((!am->right_mems) && !node_is_right_unlinked(node))
01578 unlink_from_left_mem(node);
01579 if (prefer_left_unlinking && (!parent_mem->a.np.tokens) && (!am->right_mems)) {
01580 relink_to_right_mem(node);
01581 unlink_from_left_mem(node);
01582 }
01583
01584 return node;
01585 }
01586
01587
01588
01589
01590
01591
01592
01593
01594 rete_node *split_mp_node(rete_node * mp_node)
01595 {
01596 rete_node mp_copy;
01597 rete_node *pos_node, *mem_node, *parent;
01598 byte mem_node_type, node_type;
01599 token *t;
01600
01601
01602 if (mp_node->node_type == MP_BNODE) {
01603 node_type = POSITIVE_BNODE;
01604 mem_node_type = MEMORY_BNODE;
01605 } else {
01606 node_type = UNHASHED_POSITIVE_BNODE;
01607 mem_node_type = UNHASHED_MEMORY_BNODE;
01608 }
01609
01610
01611 mp_copy = *mp_node;
01612 parent = mp_node->parent;
01613 remove_node_from_parents_list_of_children(mp_node);
01614 update_stats_for_destroying_node(mp_node);
01615
01616
01617 pos_node = mp_node;
01618
01619
01620 allocate_with_pool(¤t_agent(rete_node_pool), &mem_node);
01621 init_new_rete_node_with_type(mem_node, mem_node_type);
01622 set_sharing_factor(mem_node, mp_copy.sharing_factor);
01623
01624 mem_node->parent = parent;
01625 mem_node->next_sibling = parent->first_child;
01626 parent->first_child = mem_node;
01627 mem_node->first_child = pos_node;
01628 mem_node->b.mem.first_linked_child = NIL;
01629 mem_node->left_hash_loc_field_num = mp_copy.left_hash_loc_field_num;
01630 mem_node->left_hash_loc_levels_up = mp_copy.left_hash_loc_levels_up;
01631 mem_node->node_id = mp_copy.node_id;
01632
01633 mem_node->a.np.tokens = mp_node->a.np.tokens;
01634 for (t = mp_node->a.np.tokens; t != NIL; t = t->next_of_node)
01635 t->node = mem_node;
01636
01637
01638 init_new_rete_node_with_type(pos_node, node_type);
01639 pos_node->parent = mem_node;
01640 pos_node->first_child = mp_copy.first_child;
01641 pos_node->next_sibling = NIL;
01642 pos_node->b.posneg = mp_copy.b.posneg;
01643 relink_to_left_mem(pos_node);
01644 set_sharing_factor(pos_node, mp_copy.sharing_factor);
01645
01646
01647 if (mp_bnode_is_left_unlinked(&mp_copy))
01648 unlink_from_left_mem(pos_node);
01649
01650 return mem_node;
01651 }
01652
01653
01654
01655
01656
01657
01658
01659
01660 rete_node *merge_into_mp_node(rete_node * mem_node)
01661 {
01662 rete_node *pos_node, *mp_node, *parent;
01663 rete_node pos_copy;
01664 byte node_type;
01665 token *t;
01666
01667 pos_node = mem_node->first_child;
01668 parent = mem_node->parent;
01669
01670
01671 if ((!pos_node) || pos_node->next_sibling) {
01672 char msg[MESSAGE_SIZE];
01673 strncpy(msg, "\nrete.c: Internal error: tried to merge_into_mp_node, but <>1 child\n", MESSAGE_SIZE);
01674 msg[MESSAGE_SIZE - 1] = 0;
01675 abort_with_fatal_error(msg);
01676 }
01677
01678
01679 if (mem_node->node_type == MEMORY_BNODE) {
01680 node_type = MP_BNODE;
01681 } else {
01682 node_type = UNHASHED_MP_BNODE;
01683 }
01684
01685
01686 pos_copy = *pos_node;
01687 update_stats_for_destroying_node(pos_node);
01688
01689
01690 mp_node = pos_node;
01691 init_new_rete_node_with_type(mp_node, node_type);
01692 set_sharing_factor(mp_node, pos_copy.sharing_factor);
01693 mp_node->b.posneg = pos_copy.b.posneg;
01694
01695
01696 mp_node->a.np.tokens = mem_node->a.np.tokens;
01697 for (t = mem_node->a.np.tokens; t != NIL; t = t->next_of_node)
01698 t->node = mp_node;
01699 mp_node->left_hash_loc_field_num = mem_node->left_hash_loc_field_num;
01700 mp_node->left_hash_loc_levels_up = mem_node->left_hash_loc_levels_up;
01701 mp_node->node_id = mem_node->node_id;
01702
01703
01704 mp_node->parent = parent;
01705 mp_node->next_sibling = parent->first_child;
01706 parent->first_child = mp_node;
01707 mp_node->first_child = pos_copy.first_child;
01708
01709 remove_node_from_parents_list_of_children(mem_node);
01710 update_stats_for_destroying_node(mem_node);
01711 free_with_pool(¤t_agent(rete_node_pool), mem_node);
01712
01713
01714 make_mp_bnode_left_linked(mp_node);
01715 if (node_is_left_unlinked(&pos_copy))
01716 make_mp_bnode_left_unlinked(mp_node);
01717
01718 return mp_node;
01719 }
01720
01721
01722
01723
01724
01725
01726
01727 rete_node *make_new_mp_node(rete_node * parent, byte node_type,
01728 var_location left_hash_loc, alpha_mem * am, rete_test * rt, bool prefer_left_unlinking)
01729 {
01730 rete_node *mem_node, *pos_node;
01731 byte mem_node_type, pos_node_type;
01732
01733 if (node_type == MP_BNODE) {
01734 pos_node_type = POSITIVE_BNODE;
01735 mem_node_type = MEMORY_BNODE;
01736 } else {
01737 pos_node_type = UNHASHED_POSITIVE_BNODE;
01738 mem_node_type = UNHASHED_MEMORY_BNODE;
01739 }
01740 mem_node = make_new_mem_node(parent, mem_node_type, left_hash_loc);
01741 pos_node = make_new_positive_node(mem_node, pos_node_type, am, rt, prefer_left_unlinking);
01742 return merge_into_mp_node(mem_node);
01743 }
01744
01745
01746
01747
01748
01749
01750
01751 rete_node *make_new_negative_node(rete_node * parent, byte node_type,
01752 var_location left_hash_loc, alpha_mem * am, rete_test * rt)
01753 {
01754 rete_node *node;
01755
01756 allocate_with_pool(¤t_agent(rete_node_pool), &node);
01757 init_new_rete_node_with_type(node, node_type);
01758 node->parent = parent;
01759 node->next_sibling = parent->first_child;
01760 parent->first_child = node;
01761 node->first_child = NIL;
01762 node->left_hash_loc_field_num = left_hash_loc.field_num;
01763 node->left_hash_loc_levels_up = left_hash_loc.levels_up;
01764 node->b.posneg.other_tests = rt;
01765 node->b.posneg.alpha_mem = am;
01766 node->a.np.tokens = NIL;
01767 node->b.posneg.nearest_ancestor_with_same_am = nearest_ancestor_with_same_am(node, am);
01768 relink_to_right_mem(node);
01769
01770 node->node_id = get_next_beta_node_id();
01771
01772
01773 update_node_with_matches_from_above(node);
01774
01775
01776 if (!node->a.np.tokens)
01777 unlink_from_right_mem(node);
01778
01779 return node;
01780 }
01781
01782
01783
01784
01785
01786
01787
01788 rete_node *make_new_cn_node(rete_node * parent, rete_node * bottom_of_subconditions)
01789 {
01790 rete_node *node, *partner, *ncc_subconditions_top_node;
01791
01792
01793 ncc_subconditions_top_node = NIL;
01794 for (node = bottom_of_subconditions; node != parent; node = node->parent) {
01795 ncc_subconditions_top_node = node;
01796 }
01797
01798 allocate_with_pool(¤t_agent(rete_node_pool), &node);
01799 init_new_rete_node_with_type(node, CN_BNODE);
01800 allocate_with_pool(¤t_agent(rete_node_pool), &partner);
01801 init_new_rete_node_with_type(partner, CN_PARTNER_BNODE);
01802
01803
01804
01805 remove_node_from_parents_list_of_children(ncc_subconditions_top_node);
01806 node->parent = parent;
01807 node->next_sibling = parent->first_child;
01808 ncc_subconditions_top_node->next_sibling = node;
01809 parent->first_child = ncc_subconditions_top_node;
01810 node->first_child = NIL;
01811
01812 node->a.np.tokens = NIL;
01813 node->b.cn.partner = partner;
01814 node->node_id = get_next_beta_node_id();
01815
01816 partner->parent = bottom_of_subconditions;
01817 partner->next_sibling = bottom_of_subconditions->first_child;
01818 bottom_of_subconditions->first_child = partner;
01819 partner->first_child = NIL;
01820 partner->a.np.tokens = NIL;
01821 partner->b.cn.partner = node;
01822
01823
01824 update_node_with_matches_from_above(partner);
01825
01826 update_node_with_matches_from_above(node);
01827
01828 return node;
01829 }
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843 rete_node *make_new_production_node(rete_node * parent, production * new_prod)
01844 {
01845 rete_node *p_node;
01846
01847 allocate_with_pool(¤t_agent(rete_node_pool), &p_node);
01848 init_new_rete_node_with_type(p_node, P_BNODE);
01849 new_prod->p_node = p_node;
01850 p_node->parent = parent;
01851 p_node->next_sibling = parent->first_child;
01852 parent->first_child = p_node;
01853 p_node->first_child = NIL;
01854 p_node->b.p.prod = new_prod;
01855 p_node->a.np.tokens = NIL;
01856 p_node->b.p.tentative_assertions = NIL;
01857 p_node->b.p.tentative_retractions = NIL;
01858 return p_node;
01859 }
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874 void deallocate_rete_test_list(rete_test * rt)
01875 {
01876 rete_test *next_rt;
01877
01878 while (rt) {
01879 next_rt = rt->next;
01880
01881 if (test_is_constant_relational_test(rt->type)) {
01882 symbol_remove_ref(rt->data.constant_referent);
01883 } else if (rt->type == DISJUNCTION_RETE_TEST) {
01884 deallocate_symbol_list_removing_references(rt->data.disjunction_list);
01885 }
01886
01887 free_with_pool(¤t_agent(rete_test_pool), rt);
01888 rt = next_rt;
01889 }
01890 }
01891
01892 void deallocate_rete_node(rete_node * node)
01893 {
01894 rete_node *parent;
01895
01896
01897 if (node == current_agent(dummy_top_node))
01898 return;
01899
01900
01901 if (node->node_type == P_BNODE) {
01902 char msg[MESSAGE_SIZE];
01903 strncpy(msg, "Internal error: deallocate_rete_node() called on p-node.\n", MESSAGE_SIZE);
01904 msg[MESSAGE_SIZE - 1] = 0;
01905 abort_with_fatal_error(msg);
01906 }
01907
01908 parent = node->parent;
01909
01910
01911 if (node->node_type == CN_BNODE)
01912 deallocate_rete_node(node->b.cn.partner);
01913
01914
01915 if (!bnode_is_bottom_of_split_mp(node->node_type))
01916 while (node->a.np.tokens)
01917 remove_token_and_subtree(node->a.np.tokens);
01918
01919
01920 if (bnode_is_posneg(node->node_type)) {
01921 deallocate_rete_test_list(node->b.posneg.other_tests);
01922
01923 if (!node_is_right_unlinked(node))
01924 unlink_from_right_mem(node);
01925 remove_ref_to_alpha_mem(node->b.posneg.alpha_mem);
01926 }
01927
01928
01929 remove_node_from_parents_list_of_children(node);
01930
01931
01932 if (bnode_is_bottom_of_split_mp(node->node_type)) {
01933 if (!node_is_left_unlinked(node))
01934 unlink_from_left_mem(node);
01935
01936 if (parent->first_child && (!parent->first_child->next_sibling))
01937 merge_into_mp_node(parent);
01938 }
01939
01940 update_stats_for_destroying_node(node);
01941 free_with_pool(¤t_agent(rete_node_pool), node);
01942
01943
01944 if (!parent->first_child)
01945 deallocate_rete_node(parent);
01946 }
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978 #define var_is_bound(v) (((Symbol *)(v))->var.rete_binding_locations != NIL)
01979
01980 #define varloc_to_dummy(depth,field_num) ((void *)(((depth)<<2) + (field_num)))
01981 #define dummy_to_varloc_depth(d) (((unsigned long)(d))>>2)
01982 #define dummy_to_varloc_field_num(d) (((unsigned long)(d)) & 3)
01983
01984 #define push_var_binding(v,depth,field_num) { \
01985 void *dummy_xy312; \
01986 dummy_xy312 = varloc_to_dummy ((depth), (field_num)); \
01987 push (dummy_xy312, ((Symbol *)(v))->var.rete_binding_locations); }
01988
01989 #define pop_var_binding(v) { \
01990 cons *c_xy312; \
01991 c_xy312 = ((Symbol *)(v))->var.rete_binding_locations; \
01992 ((Symbol *)(v))->var.rete_binding_locations = c_xy312->rest; \
01993 free_cons (c_xy312); }
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005 bool find_var_location(Symbol * var, rete_node_level current_depth, var_location * result)
02006 {
02007 void *dummy;
02008 if (!var->var.rete_binding_locations)
02009 return FALSE;
02010 dummy = var->var.rete_binding_locations->first;
02011 result->levels_up = (unsigned short) (current_depth - (rete_node_level) dummy_to_varloc_depth(dummy));
02012 result->field_num = (byte) dummy_to_varloc_field_num(dummy);
02013 return TRUE;
02014 }
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027 void bind_variables_in_test(test t, rete_node_level depth, byte field_num, bool dense, list ** varlist)
02028 {
02029 Symbol *referent;
02030 complex_test *ct;
02031 cons *c;
02032
02033 if (test_is_blank_test(t))
02034 return;
02035 if (test_is_blank_or_equality_test(t)) {
02036 referent = referent_of_equality_test(t);
02037 if (referent->common.symbol_type != VARIABLE_SYMBOL_TYPE)
02038 return;
02039 if (!dense && var_is_bound(referent))
02040 return;
02041 push_var_binding(referent, depth, field_num);
02042 push(referent, *varlist);
02043 return;
02044 }
02045
02046 ct = complex_test_from_test(t);
02047 if (ct->type == CONJUNCTIVE_TEST)
02048 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
02049 bind_variables_in_test(c->first, depth, field_num, dense, varlist);
02050 }
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061 void pop_bindings_and_deallocate_list_of_variables(list * vars)
02062 {
02063 while (vars) {
02064 cons *c;
02065 c = vars;
02066 vars = vars->rest;
02067 pop_var_binding(c->first);
02068 free_cons(c);
02069 }
02070 }
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105 typedef char varnames;
02106
02107 #define one_var_to_varnames(x) ((varnames *) (x))
02108 #define var_list_to_varnames(x) ((varnames *) (((char *)(x)) + 1))
02109 #define varnames_is_one_var(x) (! (varnames_is_var_list(x)))
02110 #define varnames_is_var_list(x) (((unsigned long)(x)) & 1)
02111 #define varnames_to_one_var(x) ((Symbol *) (x))
02112 #define varnames_to_var_list(x) ((list *) (((char *)(x)) - 1))
02113
02114 typedef struct three_field_varnames_struct {
02115 varnames *id_varnames;
02116 varnames *attr_varnames;
02117 varnames *value_varnames;
02118 } three_field_varnames;
02119
02120 typedef struct node_varnames_struct {
02121 struct node_varnames_struct *parent;
02122 union varname_data_union {
02123 three_field_varnames fields;
02124 struct node_varnames_struct *bottom_of_subconditions;
02125 } data;
02126 } node_varnames;
02127
02128 varnames *add_var_to_varnames(Symbol * var, varnames * old_varnames)
02129 {
02130 cons *c1, *c2;
02131
02132 symbol_add_ref(var);
02133 if (old_varnames == NIL)
02134 return one_var_to_varnames(var);
02135 if (varnames_is_one_var(old_varnames)) {
02136 allocate_cons(&c1);
02137 allocate_cons(&c2);
02138 c1->first = var;
02139 c1->rest = c2;
02140 c2->first = varnames_to_one_var(old_varnames);
02141 c2->rest = NIL;
02142 return var_list_to_varnames(c1);
02143 }
02144
02145 allocate_cons(&c1);
02146 c1->first = var;
02147 c1->rest = varnames_to_var_list(old_varnames);
02148 return var_list_to_varnames(c1);
02149 }
02150
02151 void deallocate_varnames(varnames * vn)
02152 {
02153 Symbol *sym;
02154 list *symlist;
02155
02156 if (vn == NIL)
02157 return;
02158 if (varnames_is_one_var(vn)) {
02159 sym = varnames_to_one_var(vn);
02160 symbol_remove_ref(sym);
02161 } else {
02162 symlist = varnames_to_var_list(vn);
02163 deallocate_symbol_list_removing_references(symlist);
02164 }
02165 }
02166
02167 void deallocate_node_varnames(rete_node * node, rete_node * cutoff, node_varnames * nvn)
02168 {
02169 node_varnames *temp;
02170
02171 while (node != cutoff) {
02172 if (node->node_type == CN_BNODE) {
02173 deallocate_node_varnames(node->b.cn.partner->parent, node->parent, nvn->data.bottom_of_subconditions);
02174 } else {
02175 deallocate_varnames(nvn->data.fields.id_varnames);
02176 deallocate_varnames(nvn->data.fields.attr_varnames);
02177 deallocate_varnames(nvn->data.fields.value_varnames);
02178 }
02179 node = real_parent_node(node);
02180 temp = nvn;
02181 nvn = nvn->parent;
02182 free_with_pool(¤t_agent(node_varnames_pool), temp);
02183 }
02184 }
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198 varnames *add_unbound_varnames_in_test(test t, varnames * starting_vn)
02199 {
02200 cons *c;
02201 Symbol *referent;
02202 complex_test *ct;
02203
02204 if (test_is_blank_test(t))
02205 return starting_vn;
02206 if (test_is_blank_or_equality_test(t)) {
02207 referent = referent_of_equality_test(t);
02208 if (referent->common.symbol_type == VARIABLE_SYMBOL_TYPE)
02209 if (!var_is_bound(referent))
02210 starting_vn = add_var_to_varnames(referent, starting_vn);
02211 return starting_vn;
02212 }
02213
02214 ct = complex_test_from_test(t);
02215
02216 if (ct->type == CONJUNCTIVE_TEST) {
02217 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
02218 starting_vn = add_unbound_varnames_in_test(c->first, starting_vn);
02219 }
02220 return starting_vn;
02221 }
02222
02223 node_varnames *make_nvn_for_posneg_cond(condition * cond, node_varnames * parent_nvn)
02224 {
02225 node_varnames *new;
02226 list *vars_bound;
02227
02228 vars_bound = NIL;
02229
02230 allocate_with_pool(¤t_agent(node_varnames_pool), &new);
02231 new->parent = parent_nvn;
02232
02233
02234 new->data.fields.id_varnames = add_unbound_varnames_in_test(cond->data.tests.id_test, NIL);
02235
02236
02237 bind_variables_in_test(cond->data.tests.id_test, 0, 0, FALSE, &vars_bound);
02238 new->data.fields.attr_varnames = add_unbound_varnames_in_test(cond->data.tests.attr_test, NIL);
02239
02240
02241 bind_variables_in_test(cond->data.tests.attr_test, 0, 0, FALSE, &vars_bound);
02242 new->data.fields.value_varnames = add_unbound_varnames_in_test(cond->data.tests.value_test, NIL);
02243
02244
02245 pop_bindings_and_deallocate_list_of_variables(vars_bound);
02246
02247 return new;
02248 }
02249
02250 node_varnames *get_nvn_for_condition_list(condition * cond_list, node_varnames * parent_nvn)
02251 {
02252 node_varnames *new = NULL;
02253 condition *cond;
02254 list *vars;
02255
02256 vars = NIL;
02257
02258 for (cond = cond_list; cond != NIL; cond = cond->next) {
02259
02260 switch (cond->type) {
02261 case POSITIVE_CONDITION:
02262 new = make_nvn_for_posneg_cond(cond, parent_nvn);
02263
02264
02265 bind_variables_in_test(cond->data.tests.id_test, 0, 0, FALSE, &vars);
02266 bind_variables_in_test(cond->data.tests.attr_test, 0, 0, FALSE, &vars);
02267 bind_variables_in_test(cond->data.tests.value_test, 0, 0, FALSE, &vars);
02268 break;
02269 case NEGATIVE_CONDITION:
02270 new = make_nvn_for_posneg_cond(cond, parent_nvn);
02271 break;
02272 case CONJUNCTIVE_NEGATION_CONDITION:
02273 allocate_with_pool(¤t_agent(node_varnames_pool), &new);
02274 new->parent = parent_nvn;
02275 new->data.bottom_of_subconditions = get_nvn_for_condition_list(cond->data.ncc.top, parent_nvn);
02276 break;
02277 }
02278
02279 parent_nvn = new;
02280 }
02281
02282
02283 pop_bindings_and_deallocate_list_of_variables(vars);
02284
02285 return parent_nvn;
02286 }
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310 byte test_type_to_relational_test_type[256];
02311 byte relational_test_type_to_test_type[256];
02312
02313
02314
02315 #define EQUAL_TEST_TYPE 254
02316 #define ERROR_TEST_TYPE 255
02317
02318 void init_test_type_conversion_tables(void)
02319 {
02320 int i;
02321
02322 for (i = 0; i < 256; i++)
02323 test_type_to_relational_test_type[i] = ERROR_TEST_TYPE;
02324 for (i = 0; i < 256; i++)
02325 relational_test_type_to_test_type[i] = ERROR_TEST_TYPE;
02326
02327
02328 test_type_to_relational_test_type[NOT_EQUAL_TEST] = RELATIONAL_NOT_EQUAL_RETE_TEST;
02329 test_type_to_relational_test_type[LESS_TEST] = RELATIONAL_LESS_RETE_TEST;
02330 test_type_to_relational_test_type[GREATER_TEST] = RELATIONAL_GREATER_RETE_TEST;
02331 test_type_to_relational_test_type[LESS_OR_EQUAL_TEST] = RELATIONAL_LESS_OR_EQUAL_RETE_TEST;
02332 test_type_to_relational_test_type[GREATER_OR_EQUAL_TEST] = RELATIONAL_GREATER_OR_EQUAL_RETE_TEST;
02333 test_type_to_relational_test_type[SAME_TYPE_TEST] = RELATIONAL_SAME_TYPE_RETE_TEST;
02334
02335 relational_test_type_to_test_type[RELATIONAL_EQUAL_RETE_TEST] = EQUAL_TEST_TYPE;
02336 relational_test_type_to_test_type[RELATIONAL_NOT_EQUAL_RETE_TEST] = NOT_EQUAL_TEST;
02337 relational_test_type_to_test_type[RELATIONAL_LESS_RETE_TEST] = LESS_TEST;
02338 relational_test_type_to_test_type[RELATIONAL_GREATER_RETE_TEST] = GREATER_TEST;
02339 relational_test_type_to_test_type[RELATIONAL_LESS_OR_EQUAL_RETE_TEST] = LESS_OR_EQUAL_TEST;
02340 relational_test_type_to_test_type[RELATIONAL_GREATER_OR_EQUAL_RETE_TEST] = GREATER_OR_EQUAL_TEST;
02341 relational_test_type_to_test_type[RELATIONAL_SAME_TYPE_RETE_TEST] = SAME_TYPE_TEST;
02342 }
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365 void add_rete_tests_for_test(test t,
02366 rete_node_level current_depth, byte field_num, rete_test ** rt, Symbol ** alpha_constant)
02367 {
02368 var_location where;
02369 cons *c;
02370 rete_test *new_rt;
02371 complex_test *ct;
02372 Symbol *referent;
02373
02374 if (test_is_blank_test(t))
02375 return;
02376
02377 if (test_is_blank_or_equality_test(t)) {
02378 referent = referent_of_equality_test(t);
02379
02380
02381 if ((referent->common.symbol_type != VARIABLE_SYMBOL_TYPE) && (*alpha_constant == NIL)) {
02382 *alpha_constant = referent;
02383 return;
02384 }
02385
02386
02387 if (referent->common.symbol_type != VARIABLE_SYMBOL_TYPE) {
02388 allocate_with_pool(¤t_agent(rete_test_pool), &new_rt);
02389 new_rt->right_field_num = field_num;
02390 new_rt->type = CONSTANT_RELATIONAL_RETE_TEST + RELATIONAL_EQUAL_RETE_TEST;
02391 new_rt->data.constant_referent = referent;
02392 symbol_add_ref(referent);
02393 new_rt->next = *rt;
02394 *rt = new_rt;
02395 return;
02396 }
02397
02398
02399 if (!find_var_location(referent, current_depth, &where)) {
02400 char msg[MESSAGE_SIZE];
02401 print_with_symbols("Error: Rete build found test of unbound var: %y\n", referent);
02402 snprintf(msg, MESSAGE_SIZE, "Error: Rete build found test of unbound var: %s\n",
02403 symbol_to_string(referent, TRUE, NIL, 0));
02404 msg[MESSAGE_SIZE - 1] = 0;
02405 abort_with_fatal_error(msg);
02406 }
02407 if ((where.levels_up == 0) && (where.field_num == field_num))
02408 return;
02409
02410
02411 allocate_with_pool(¤t_agent(rete_test_pool), &new_rt);
02412 new_rt->right_field_num = field_num;
02413 new_rt->type = VARIABLE_RELATIONAL_RETE_TEST + RELATIONAL_EQUAL_RETE_TEST;
02414 new_rt->data.variable_referent = where;
02415 new_rt->next = *rt;
02416 *rt = new_rt;
02417 return;
02418 }
02419
02420 ct = complex_test_from_test(t);
02421
02422 switch (ct->type) {
02423
02424 case NOT_EQUAL_TEST:
02425 case LESS_TEST:
02426 case GREATER_TEST:
02427 case LESS_OR_EQUAL_TEST:
02428 case GREATER_OR_EQUAL_TEST:
02429 case SAME_TYPE_TEST:
02430
02431 if (ct->data.referent->common.symbol_type != VARIABLE_SYMBOL_TYPE) {
02432 allocate_with_pool(¤t_agent(rete_test_pool), &new_rt);
02433 new_rt->right_field_num = field_num;
02434 new_rt->type = (unsigned char) (CONSTANT_RELATIONAL_RETE_TEST +
02435 test_type_to_relational_test_type[ct->type]);
02436 new_rt->data.constant_referent = ct->data.referent;
02437 symbol_add_ref(ct->data.referent);
02438 new_rt->next = *rt;
02439 *rt = new_rt;
02440 return;
02441 }
02442
02443 if (!find_var_location(ct->data.referent, current_depth, &where)) {
02444 char msg[MESSAGE_SIZE];
02445 print_with_symbols("Error: Rete build found test of unbound var: %y\n", ct->data.referent);
02446 snprintf(msg, MESSAGE_SIZE, "Error: Rete build found test of unbound var: %s\n",
02447 symbol_to_string(ct->data.referent, TRUE, NIL, 0));
02448 msg[MESSAGE_SIZE - 1] = 0;
02449 abort_with_fatal_error(msg);
02450 }
02451 allocate_with_pool(¤t_agent(rete_test_pool), &new_rt);
02452 new_rt->right_field_num = field_num;
02453 new_rt->type = (unsigned char) (VARIABLE_RELATIONAL_RETE_TEST + test_type_to_relational_test_type[ct->type]);
02454 new_rt->data.variable_referent = where;
02455 new_rt->next = *rt;
02456 *rt = new_rt;
02457 return;
02458
02459 case DISJUNCTION_TEST:
02460 allocate_with_pool(¤t_agent(rete_test_pool), &new_rt);
02461 new_rt->right_field_num = field_num;
02462 new_rt->type = DISJUNCTION_RETE_TEST;
02463 new_rt->data.disjunction_list = copy_symbol_list_adding_references(ct->data.disjunction_list);
02464 new_rt->next = *rt;
02465 *rt = new_rt;
02466 return;
02467
02468 case CONJUNCTIVE_TEST:
02469 for (c = ct->data.conjunct_list; c != NIL; c = c->rest) {
02470 add_rete_tests_for_test(c->first, current_depth, field_num, rt, alpha_constant);
02471 }
02472 return;
02473
02474 case GOAL_ID_TEST:
02475 allocate_with_pool(¤t_agent(rete_test_pool), &new_rt);
02476 new_rt->type = ID_IS_GOAL_RETE_TEST;
02477 new_rt->right_field_num = 0;
02478 new_rt->next = *rt;
02479 *rt = new_rt;
02480 return;
02481
02482 case IMPASSE_ID_TEST:
02483 allocate_with_pool(¤t_agent(rete_test_pool), &new_rt);
02484 new_rt->type = ID_IS_IMPASSE_RETE_TEST;
02485 new_rt->right_field_num = 0;
02486 new_rt->next = *rt;
02487 *rt = new_rt;
02488 return;
02489
02490 default:
02491 {
02492 char msg[MESSAGE_SIZE];
02493 snprintf(msg, MESSAGE_SIZE, "Error: found bad test type %d while building rete\n", ct->type);
02494 msg[MESSAGE_SIZE - 1] = 0;
02495 abort_with_fatal_error(msg);
02496 }
02497 }
02498 }
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517 bool single_rete_tests_are_identical(rete_test * rt1, rete_test * rt2)
02518 {
02519 cons *c1, *c2;
02520
02521 if (rt1->type != rt2->type)
02522 return FALSE;
02523
02524 if (rt1->right_field_num != rt2->right_field_num)
02525 return FALSE;
02526
02527 if (test_is_variable_relational_test(rt1->type))
02528 return (bool) (var_locations_equal(rt1->data.variable_referent, rt2->data.variable_referent));
02529
02530 if (test_is_constant_relational_test(rt1->type)) {
02531 return (bool) (rt1->data.constant_referent == rt2->data.constant_referent);
02532 }
02533
02534 if (rt1->type == ID_IS_GOAL_RETE_TEST)
02535 return TRUE;
02536 if (rt1->type == ID_IS_IMPASSE_RETE_TEST)
02537 return TRUE;
02538
02539 if (rt1->type == DISJUNCTION_RETE_TEST) {
02540 c1 = rt1->data.disjunction_list;
02541 c2 = rt2->data.disjunction_list;
02542 while ((c1 != NIL) && (c2 != NIL)) {
02543 if (c1->first != c2->first)
02544 return FALSE;
02545 c1 = c1->rest;
02546 c2 = c2->rest;
02547 }
02548 if (c1 == c2)
02549 return TRUE;
02550 return FALSE;
02551 }
02552 {
02553 char msg[MESSAGE_SIZE];
02554 strncpy(msg, "Internal error: bad rete test type in single_rete_tests_are_identical\n", MESSAGE_SIZE);
02555 msg[MESSAGE_SIZE - 1] = 0;
02556 abort_with_fatal_error(msg);
02557 }
02558 return FALSE;
02559 }
02560
02561 bool rete_test_lists_are_identical(rete_test * rt1, rete_test * rt2)
02562 {
02563 while (rt1 && rt2) {
02564 if (!single_rete_tests_are_identical(rt1, rt2))
02565 return FALSE;
02566 rt1 = rt1->next;
02567 rt2 = rt2->next;
02568 }
02569 if (rt1 == rt2)
02570 return TRUE;
02571 return FALSE;
02572 }
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583 bool extract_rete_test_to_hash_with(rete_test ** rt, var_location * dest_hash_loc)
02584 {
02585 rete_test *prev, *current;
02586
02587
02588 prev = NIL;
02589 for (current = *rt; current != NIL; prev = current, current = current->next)
02590 if (current->type == VARIABLE_RELATIONAL_RETE_TEST + RELATIONAL_EQUAL_RETE_TEST)
02591 break;
02592
02593 if (!current)
02594 return FALSE;
02595
02596
02597 if (prev)
02598 prev->next = current->next;
02599 else
02600 *rt = current->next;
02601
02602
02603 *dest_hash_loc = current->data.variable_referent;
02604 current->next = NIL;
02605 deallocate_rete_test_list(current);
02606 return TRUE;
02607 }
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619 rete_node *make_node_for_positive_cond(condition * cond, rete_node_level current_depth, rete_node * parent)
02620 {
02621 byte pos_node_type, mem_node_type, mp_node_type;
02622 Symbol *alpha_id, *alpha_attr, *alpha_value;
02623 rete_node *node, *mem_node, *mp_node;
02624 alpha_mem *am;
02625 rete_test *rt;
02626 bool hash_this_node;
02627 var_location left_hash_loc;
02628 list *vars_bound_here;
02629
02630 alpha_id = alpha_attr = alpha_value = NIL;
02631 rt = NIL;
02632 vars_bound_here = NIL;
02633
02634
02635 bind_variables_in_test(cond->data.tests.id_test, current_depth, 0, FALSE, &vars_bound_here);
02636 bind_variables_in_test(cond->data.tests.attr_test, current_depth, 1, FALSE, &vars_bound_here);
02637 bind_variables_in_test(cond->data.tests.value_test, current_depth, 2, FALSE, &vars_bound_here);
02638
02639
02640 add_rete_tests_for_test(cond->data.tests.id_test, current_depth, 0, &rt, &alpha_id);
02641 hash_this_node = extract_rete_test_to_hash_with(&rt, &left_hash_loc);
02642 add_rete_tests_for_test(cond->data.tests.attr_test, current_depth, 1, &rt, &alpha_attr);
02643 add_rete_tests_for_test(cond->data.tests.value_test, current_depth, 2, &rt, &alpha_value);
02644
02645
02646 pop_bindings_and_deallocate_list_of_variables(vars_bound_here);
02647
02648
02649 am = find_or_make_alpha_mem(alpha_id, alpha_attr, alpha_value, cond->test_for_acceptable_preference);
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660 if (hash_this_node) {
02661 pos_node_type = POSITIVE_BNODE;
02662 mem_node_type = MEMORY_BNODE;
02663 mp_node_type = MP_BNODE;
02664 } else {
02665 pos_node_type = UNHASHED_POSITIVE_BNODE;
02666 mem_node_type = UNHASHED_MEMORY_BNODE;
02667 mp_node_type = UNHASHED_MP_BNODE;
02668 }
02669
02670
02671 for (mem_node = parent->first_child; mem_node != NIL; mem_node = mem_node->next_sibling)
02672 if ((mem_node->node_type == mem_node_type) &&
02673 ((!hash_this_node) ||
02674 ((mem_node->left_hash_loc_field_num == left_hash_loc.field_num) &&
02675 (mem_node->left_hash_loc_levels_up == left_hash_loc.levels_up))))
02676 break;
02677
02678 if (mem_node) {
02679
02680 for (node = mem_node->first_child; node != NIL; node = node->next_sibling)
02681 if ((node->node_type == pos_node_type) &&
02682 (am == node->b.posneg.alpha_mem) && rete_test_lists_are_identical(node->b.posneg.other_tests, rt))
02683 break;
02684
02685 if (node) {
02686 deallocate_rete_test_list(rt);
02687 remove_ref_to_alpha_mem(am);
02688 return node;
02689 } else {
02690 node = make_new_positive_node(mem_node, pos_node_type, am, rt, FALSE);
02691 return node;
02692 }
02693 }
02694
02695
02696 for (mp_node = parent->first_child; mp_node != NIL; mp_node = mp_node->next_sibling)
02697 if ((mp_node->node_type == mp_node_type) &&
02698 ((!hash_this_node) ||
02699 ((mp_node->left_hash_loc_field_num == left_hash_loc.field_num) &&
02700 (mp_node->left_hash_loc_levels_up == left_hash_loc.levels_up))))
02701 break;
02702
02703 if (mp_node) {
02704 if ((am == mp_node->b.posneg.alpha_mem) && rete_test_lists_are_identical(mp_node->b.posneg.other_tests, rt)) {
02705
02706 deallocate_rete_test_list(rt);
02707 remove_ref_to_alpha_mem(am);
02708 return mp_node;
02709 }
02710
02711
02712 mem_node = split_mp_node(mp_node);
02713 node = make_new_positive_node(mem_node, pos_node_type, am, rt, FALSE);
02714 return node;
02715 }
02716
02717
02718 return make_new_mp_node(parent, mp_node_type, left_hash_loc, am, rt, FALSE);
02719 }
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731 rete_node *make_node_for_negative_cond(condition * cond, rete_node_level current_depth, rete_node * parent)
02732 {
02733 byte node_type;
02734 Symbol *alpha_id, *alpha_attr, *alpha_value;
02735 rete_node *node;
02736 alpha_mem *am;
02737 rete_test *rt;
02738 bool hash_this_node;
02739 var_location left_hash_loc;
02740 list *vars_bound_here;
02741
02742 alpha_id = alpha_attr = alpha_value = NIL;
02743 rt = NIL;
02744 vars_bound_here = NIL;
02745
02746
02747 bind_variables_in_test(cond->data.tests.id_test, current_depth, 0, FALSE, &vars_bound_here);
02748 bind_variables_in_test(cond->data.tests.attr_test, current_depth, 1, FALSE, &vars_bound_here);
02749 bind_variables_in_test(cond->data.tests.value_test, current_depth, 2, FALSE, &vars_bound_here);
02750
02751
02752 add_rete_tests_for_test(cond->data.tests.id_test, current_depth, 0, &rt, &alpha_id);
02753 hash_this_node = extract_rete_test_to_hash_with(&rt, &left_hash_loc);
02754 add_rete_tests_for_test(cond->data.tests.attr_test, current_depth, 1, &rt, &alpha_attr);
02755 add_rete_tests_for_test(cond->data.tests.value_test, current_depth, 2, &rt, &alpha_value);
02756
02757
02758 pop_bindings_and_deallocate_list_of_variables(vars_bound_here);
02759
02760
02761 am = find_or_make_alpha_mem(alpha_id, alpha_attr, alpha_value, cond->test_for_acceptable_preference);
02762
02763
02764 node_type = (bool) (hash_this_node ? NEGATIVE_BNODE : UNHASHED_NEGATIVE_BNODE);
02765
02766
02767 for (node = parent->first_child; node != NIL; node = node->next_sibling)
02768 if ((node->node_type == node_type) &&
02769 (am == node->b.posneg.alpha_mem) &&
02770 ((!hash_this_node) ||
02771 ((node->left_hash_loc_field_num == left_hash_loc.field_num) &&
02772 (node->left_hash_loc_levels_up == left_hash_loc.levels_up))) &&
02773 rete_test_lists_are_identical(node->b.posneg.other_tests, rt))
02774 break;
02775
02776 if (node) {
02777 deallocate_rete_test_list(rt);
02778 remove_ref_to_alpha_mem(am);
02779 return node;
02780 } else {
02781 node = make_new_negative_node(parent, node_type, left_hash_loc, am, rt);
02782 return node;
02783 }
02784 }
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806 void build_network_for_condition_list(condition * cond_list,
02807 rete_node_level depth_of_first_cond,
02808 rete_node * parent,
02809 rete_node ** dest_bottom_node,
02810 rete_node_level * dest_bottom_depth, list ** dest_vars_bound)
02811 {
02812 rete_node *node, *new_node, *child, *subconditions_bottom_node;
02813 condition *cond;
02814 rete_node_level current_depth;
02815 list *vars_bound;
02816
02817 node = parent;
02818 current_depth = depth_of_first_cond;
02819 vars_bound = NIL;
02820
02821 for (cond = cond_list; cond != NIL; cond = cond->next) {
02822 switch (cond->type) {
02823
02824 case POSITIVE_CONDITION:
02825 new_node = make_node_for_positive_cond(cond, current_depth, node);
02826
02827 bind_variables_in_test(cond->data.tests.id_test, current_depth, 0, TRUE, &vars_bound);
02828 bind_variables_in_test(cond->data.tests.attr_test, current_depth, 1, TRUE, &vars_bound);
02829 bind_variables_in_test(cond->data.tests.value_test, current_depth, 2, TRUE, &vars_bound);
02830 break;
02831
02832 case NEGATIVE_CONDITION:
02833 new_node = make_node_for_negative_cond(cond, current_depth, node);
02834 break;
02835
02836 case CONJUNCTIVE_NEGATION_CONDITION:
02837
02838 build_network_for_condition_list(cond->data.ncc.top, current_depth,
02839 node, &subconditions_bottom_node, NIL, NIL);
02840
02841 for (child = node->first_child; child != NIL; child = child->next_sibling)
02842 if (child->node_type == CN_BNODE)
02843 if (child->b.cn.partner->parent == subconditions_bottom_node)
02844 break;
02845
02846 if (child) {
02847 new_node = child;
02848 } else {
02849 new_node = make_new_cn_node(node, subconditions_bottom_node);
02850 }
02851 break;
02852
02853 default:
02854 new_node = NIL;
02855 }
02856
02857 node = new_node;
02858 current_depth++;
02859 }
02860
02861
02862 if (dest_bottom_node)
02863 *dest_bottom_node = node;
02864 if (dest_bottom_depth)
02865 *dest_bottom_depth = (unsigned short) (current_depth - 1);
02866 if (dest_vars_bound) {
02867 *dest_vars_bound = vars_bound;
02868 } else {
02869 pop_bindings_and_deallocate_list_of_variables(vars_bound);
02870 }
02871 }
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890 bool same_rhs(action * rhs1, action * rhs2)
02891 {
02892 action *a1, *a2;
02893
02894
02895
02896
02897
02898
02899
02900 a1 = rhs1;
02901 a2 = rhs2;
02902
02903 while (a1 && a2) {
02904 if (a1->type == FUNCALL_ACTION)
02905 return FALSE;
02906 if (a2->type == FUNCALL_ACTION)
02907 return FALSE;
02908 if (a1->preference_type != a2->preference_type)
02909 return FALSE;
02910 if (a1->id != a2->id)
02911 return FALSE;
02912 if (a1->attr != a2->attr)
02913 return FALSE;
02914 if (a1->value != a2->value)
02915 return FALSE;
02916 if (preference_is_binary(a1->preference_type))
02917 if (a1->referent != a2->referent)
02918 return FALSE;
02919 a1 = a1->next;
02920 a2 = a2->next;
02921 }
02922
02923
02924
02925 if (a1 != a2)
02926 return FALSE;
02927
02928
02929 return TRUE;
02930 }
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949 list *rhs_unbound_vars_for_new_prod;
02950
02951
02952 unsigned long num_rhs_unbound_vars_for_new_prod;
02953
02954
02955 tc_number rhs_unbound_vars_tc;
02956
02957 void fixup_rhs_value_variable_references(rhs_value * rv, rete_node_level bottom_depth)
02958 {
02959 cons *c;
02960 Symbol *sym;
02961 var_location var_loc;
02962 unsigned long index;
02963
02964 if (rhs_value_is_symbol(*rv)) {
02965 sym = rhs_value_to_symbol(*rv);
02966 if (sym->common.symbol_type != VARIABLE_SYMBOL_TYPE)
02967 return;
02968
02969 if (find_var_location(sym, (rete_node_level) (bottom_depth + 1), &var_loc)) {
02970
02971 symbol_remove_ref(sym);
02972 *rv = reteloc_to_rhs_value(var_loc.field_num, var_loc.levels_up - 1);
02973 } else {
02974
02975 if (sym->var.tc_num != rhs_unbound_vars_tc) {
02976 symbol_add_ref(sym);
02977 push(sym, rhs_unbound_vars_for_new_prod);
02978 sym->var.tc_num = rhs_unbound_vars_tc;
02979 index = num_rhs_unbound_vars_for_new_prod++;
02980 sym->var.current_binding_value = (Symbol *) index;
02981 } else {
02982 index = (unsigned long) (sym->var.current_binding_value);
02983 }
02984 *rv = unboundvar_to_rhs_value(index);
02985 symbol_remove_ref(sym);
02986 }
02987 return;
02988 }
02989
02990 if (rhs_value_is_funcall(*rv)) {
02991 for (c = rhs_value_to_funcall_list(*rv)->rest; c != NIL; c = c->rest)
02992 fixup_rhs_value_variable_references((rhs_value *) (&(c->first)), bottom_depth);
02993 }
02994 }
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007 void update_max_rhs_unbound_variables(unsigned long num_for_new_production)
03008 {
03009 if (num_for_new_production > current_agent(max_rhs_unbound_variables)) {
03010 free_memory(current_agent(rhs_variable_bindings), MISCELLANEOUS_MEM_USAGE);
03011 current_agent(max_rhs_unbound_variables) = num_for_new_production;
03012 current_agent(rhs_variable_bindings) = (Symbol **)
03013 allocate_memory_and_zerofill(current_agent(max_rhs_unbound_variables) *
03014 sizeof(Symbol *), MISCELLANEOUS_MEM_USAGE);
03015 }
03016 }
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043 byte add_production_to_rete(production * p,
03044 condition * lhs_top, instantiation * refracted_inst, bool warn_on_duplicates)
03045 {
03046 rete_node *bottom_node, *p_node;
03047 rete_node_level bottom_depth;
03048 list *vars_bound;
03049 ms_change *msc;
03050 action *a;
03051 byte production_addition_result;
03052
03053
03054 build_network_for_condition_list(lhs_top, 1, current_agent(dummy_top_node),
03055 &bottom_node, &bottom_depth, &vars_bound);
03056
03057
03058
03059 rhs_unbound_vars_for_new_prod = NIL;
03060 num_rhs_unbound_vars_for_new_prod = 0;
03061 rhs_unbound_vars_tc = get_new_tc_number();
03062 for (a = p->action_list; a != NIL; a = a->next) {
03063 fixup_rhs_value_variable_references(&(a->value), bottom_depth);
03064 if (a->type == MAKE_ACTION) {
03065 fixup_rhs_value_variable_references(&(a->id), bottom_depth);
03066 fixup_rhs_value_variable_references(&(a->attr), bottom_depth);
03067 if (preference_is_binary(a->preference_type))
03068 fixup_rhs_value_variable_references(&(a->referent), bottom_depth);
03069 }
03070 }
03071
03072
03073 pop_bindings_and_deallocate_list_of_variables(vars_bound);
03074
03075 update_max_rhs_unbound_variables(num_rhs_unbound_vars_for_new_prod);
03076
03077
03078 for (p_node = bottom_node->first_child; p_node != NIL; p_node = p_node->next_sibling) {
03079 if (p_node->node_type != P_BNODE)
03080 continue;
03081 if (!same_rhs(p_node->b.p.prod->action_list, p->action_list))
03082 continue;
03083
03084 if (warn_on_duplicates)
03085 print_with_symbols("\nIgnoring %y because it is a duplicate of %y ", p->name, p_node->b.p.prod->name);
03086 deallocate_symbol_list_removing_references(rhs_unbound_vars_for_new_prod);
03087 return DUPLICATE_PRODUCTION;
03088 }
03089
03090
03091 p_node = make_new_production_node(bottom_node, p);
03092 adjust_sharing_factors_from_here_to_top(p_node, 1);
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130 if (refracted_inst) {
03131 insert_at_head_of_dll(p->instantiations, refracted_inst, next, prev);
03132 refracted_inst->rete_token = NIL;
03133 refracted_inst->rete_wme = NIL;
03134 allocate_with_pool(¤t_agent(ms_change_pool), &msc);
03135 msc->inst = refracted_inst;
03136 msc->p_node = p_node;
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150 msc->level = 0;
03151 msc->goal = NIL;
03152 #ifndef SOAR_8_ONLY
03153 if (current_agent(operand2_mode)) {
03154 #endif
03155
03156 #ifdef DEBUG_WATERFALL
03157 print_with_symbols("\n %y is a refracted instantiation", refracted_inst->prod->name);
03158 #endif
03159
03160 insert_at_head_of_dll(current_agent(nil_goal_retractions), msc, next_in_level, prev_in_level);
03161 #ifndef SOAR_8_ONLY
03162 }
03163 #endif
03164
03165
03166 #ifdef BUG_139_WORKAROUND
03167 msc->p_node->b.p.prod->already_fired = 0;
03168 #endif
03169
03170 insert_at_head_of_dll(current_agent(ms_retractions), msc, next, prev);
03171 insert_at_head_of_dll(p_node->b.p.tentative_retractions, msc, next_of_node, prev_of_node);
03172 }
03173
03174
03175 update_node_with_matches_from_above(p_node);
03176
03177
03178 if (!refracted_inst) {
03179 production_addition_result = NO_REFRACTED_INST;
03180 } else {
03181 remove_from_dll(p->instantiations, refracted_inst, next, prev);
03182 if (p_node->b.p.tentative_retractions) {
03183 production_addition_result = REFRACTED_INST_DID_NOT_MATCH;
03184 msc = p_node->b.p.tentative_retractions;
03185 p_node->b.p.tentative_retractions = NIL;
03186 remove_from_dll(current_agent(ms_retractions), msc, next, prev);
03187
03188 #ifndef SOAR_8_ONLY
03189 if (current_agent(operand2_mode)) {
03190 #endif
03191 if (msc->goal) {
03192 remove_from_dll(msc->goal->id.ms_retractions, msc, next_in_level, prev_in_level);
03193 } else {
03194 remove_from_dll(current_agent(nil_goal_retractions), msc, next_in_level, prev_in_level);
03195 }
03196
03197 #ifndef SOAR_8_ONLY
03198 }
03199 #endif
03200
03201
03202 free_with_pool(¤t_agent(ms_change_pool), msc);
03203
03204 } else {
03205 production_addition_result = REFRACTED_INST_MATCHED;
03206 }
03207 }
03208
03209
03210 if ((p->type == CHUNK_PRODUCTION_TYPE) && discard_chunk_varnames) {
03211 p->p_node->b.p.parents_nvn = NIL;
03212 p->rhs_unbound_variables = NIL;
03213 deallocate_symbol_list_removing_references(rhs_unbound_vars_for_new_prod);
03214 } else {
03215 p->p_node->b.p.parents_nvn = get_nvn_for_condition_list(lhs_top, NIL);
03216 p->rhs_unbound_variables = destructively_reverse_list(rhs_unbound_vars_for_new_prod);
03217 }
03218
03219 #ifndef FEW_CALLBACKS
03220
03221
03222 soar_invoke_callbacks(soar_agent, PRODUCTION_JUST_ADDED_CALLBACK, (soar_call_data) p);
03223 #endif
03224
03225 return production_addition_result;
03226 }
03227
03228
03229
03230
03231
03232
03233
03234
03235 void excise_production_from_rete(production * p)
03236 {
03237 rete_node *p_node, *parent;
03238 ms_change *msc;
03239
03240 #ifndef FEW_CALLBACKS
03241 soar_invoke_callbacks(soar_agent, PRODUCTION_JUST_ABOUT_TO_BE_EXCISED_CALLBACK, (soar_call_data) p);
03242 #endif
03243
03244 p_node = p->p_node;
03245 p->p_node = NIL;
03246 parent = p_node->parent;
03247
03248
03249 if (p_node->b.p.parents_nvn)
03250 deallocate_node_varnames(parent, current_agent(dummy_top_node), p_node->b.p.parents_nvn);
03251
03252
03253
03254 while (p_node->a.np.tokens)
03255 remove_token_and_subtree(p_node->a.np.tokens);
03256
03257
03258
03259
03260 for (msc = p_node->b.p.tentative_retractions; msc != NIL; msc = msc->next_of_node)
03261 msc->p_node = NIL;
03262
03263
03264 remove_node_from_parents_list_of_children(p_node);
03265 update_stats_for_destroying_node(p_node);
03266 free_with_pool(¤t_agent(rete_node_pool), p_node);
03267
03268
03269 adjust_sharing_factors_from_here_to_top(parent, -1);
03270
03271
03272 if (!parent->first_child)
03273 deallocate_rete_node(parent);
03274 }
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314 void add_gensymmed_equality_test(test * t, char first_letter)
03315 {
03316 Symbol *new;
03317 test eq_test;
03318 char prefix[2];
03319
03320 prefix[0] = first_letter;
03321 prefix[1] = 0;
03322 new = generate_new_variable(prefix);
03323 eq_test = make_equality_test(new);
03324 symbol_remove_ref(new);
03325 add_new_test_to_test(t, eq_test);
03326 }
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339 Symbol *var_bound_in_reconstructed_conds(condition * cond,
03340 byte where_field_num, rete_node_level where_levels_up)
03341 {
03342 test t;
03343 complex_test *ct;
03344 cons *c;
03345
03346 while (where_levels_up) {
03347 where_levels_up--;
03348 cond = cond->prev;
03349 }
03350
03351 if (where_field_num == 0)
03352 t = cond->data.tests.id_test;
03353 else if (where_field_num == 1)
03354 t = cond->data.tests.attr_test;
03355 else
03356 t = cond->data.tests.value_test;
03357
03358 if (test_is_blank_test(t))
03359 goto abort_var_bound_in_reconstructed_conds;
03360 if (test_is_blank_or_equality_test(t))
03361 return referent_of_equality_test(t);
03362
03363 ct = complex_test_from_test(t);
03364 if (ct->type == CONJUNCTIVE_TEST) {
03365 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
03366 if ((!test_is_blank_test((test) (c->first))) && (test_is_blank_or_equality_test((test) (c->first))))
03367 return referent_of_equality_test((test) (c->first));
03368 }
03369
03370 abort_var_bound_in_reconstructed_conds:
03371 {
03372 char msg[MESSAGE_SIZE];
03373 strncpy(msg, "Internal error in var_bound_in_reconstructed_conds\n", MESSAGE_SIZE);
03374 msg[MESSAGE_SIZE - 1] = 0;
03375 abort_with_fatal_error(msg);
03376 }
03377 return 0;
03378 }
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390 void add_rete_test_list_to_tests(condition * cond,
03391 rete_test * rt)
03392 {
03393 Symbol *referent;
03394 test new;
03395 complex_test *new_ct;
03396 byte test_type;
03397
03398 for (; rt != NIL; rt = rt->next) {
03399
03400 if (rt->type == ID_IS_GOAL_RETE_TEST) {
03401 allocate_with_pool(¤t_agent(complex_test_pool), &new_ct);
03402 new = make_test_from_complex_test(new_ct);
03403 new_ct->type = GOAL_ID_TEST;
03404 } else if (rt->type == ID_IS_IMPASSE_RETE_TEST) {
03405 allocate_with_pool(¤t_agent(complex_test_pool), &new_ct);
03406 new = make_test_from_complex_test(new_ct);
03407 new_ct->type = IMPASSE_ID_TEST;
03408 } else if (rt->type == DISJUNCTION_RETE_TEST) {
03409 allocate_with_pool(¤t_agent(complex_test_pool), &new_ct);
03410 new = make_test_from_complex_test(new_ct);
03411 new_ct->type = DISJUNCTION_TEST;
03412 new_ct->data.disjunction_list = copy_symbol_list_adding_references(rt->data.disjunction_list);
03413 } else if (test_is_constant_relational_test(rt->type)) {
03414 test_type = relational_test_type_to_test_type[kind_of_relational_test(rt->type)];
03415 referent = rt->data.constant_referent;
03416 symbol_add_ref(referent);
03417 if (test_type == EQUAL_TEST_TYPE) {
03418 new = make_equality_test_without_adding_reference(referent);
03419 } else {
03420 allocate_with_pool(¤t_agent(complex_test_pool), &new_ct);
03421 new = make_test_from_complex_test(new_ct);
03422 new_ct->type = test_type;
03423 new_ct->data.referent = referent;
03424 }
03425 } else if (test_is_variable_relational_test(rt->type)) {
03426 test_type = relational_test_type_to_test_type[kind_of_relational_test(rt->type)];
03427 if (!rt->data.variable_referent.levels_up) {
03428
03429
03430
03431
03432 if (rt->data.variable_referent.field_num == 0) {
03433 if (!test_includes_equality_test_for_symbol(cond->data.tests.id_test, NIL))
03434 add_gensymmed_equality_test(&(cond->data.tests.id_test), 's');
03435 } else if (rt->data.variable_referent.field_num == 1) {
03436 if (!test_includes_equality_test_for_symbol(cond->data.tests.attr_test, NIL))
03437 add_gensymmed_equality_test(&(cond->data.tests.attr_test), 'a');
03438 } else {
03439 if (!test_includes_equality_test_for_symbol(cond->data.tests.value_test, NIL))
03440 add_gensymmed_equality_test(&(cond->data.tests.value_test),
03441 first_letter_from_test(cond->data.tests.attr_test));
03442 }
03443 }
03444 referent = var_bound_in_reconstructed_conds(cond,
03445 rt->data.variable_referent.field_num,
03446 rt->data.variable_referent.levels_up);
03447 symbol_add_ref(referent);
03448 if (test_type == EQUAL_TEST_TYPE) {
03449 new = make_equality_test_without_adding_reference(referent);
03450 } else {
03451 allocate_with_pool(¤t_agent(complex_test_pool), &new_ct);
03452 new = make_test_from_complex_test(new_ct);
03453 new_ct->type = test_type;
03454 new_ct->data.referent = referent;
03455 }
03456 } else {
03457 char msg[MESSAGE_SIZE];
03458 strncpy(msg, "Error: bad test_type in add_rete_test_to_test\n", MESSAGE_SIZE);
03459 msg[MESSAGE_SIZE - 1] = 0;
03460 abort_with_fatal_error(msg);
03461 new = NIL;
03462 }
03463
03464 if (rt->right_field_num == 0)
03465 add_new_test_to_test(&(cond->data.tests.id_test), new);
03466 else if (rt->right_field_num == 2)
03467 add_new_test_to_test(&(cond->data.tests.value_test), new);
03468 else
03469 add_new_test_to_test(&(cond->data.tests.attr_test), new);
03470 }
03471 }
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486 not *nots_found_in_production;
03487
03488 void collect_nots(rete_test * rt, wme * right_wme, condition * cond)
03489 {
03490 not *new_not;
03491 Symbol *right_sym;
03492 Symbol *referent;
03493
03494 for (; rt != NIL; rt = rt->next) {
03495
03496 if (!test_is_not_equal_test(rt->type))
03497 continue;
03498
03499 right_sym = field_from_wme(right_wme, rt->right_field_num);
03500
03501 if (right_sym->common.symbol_type != IDENTIFIER_SYMBOL_TYPE)
03502 continue;
03503
03504 if (rt->type == CONSTANT_RELATIONAL_RETE_TEST + RELATIONAL_NOT_EQUAL_RETE_TEST) {
03505 referent = rt->data.constant_referent;
03506 if (referent->common.symbol_type != IDENTIFIER_SYMBOL_TYPE)
03507 continue;
03508 allocate_with_pool(¤t_agent(not_pool), &new_not);
03509 new_not->next = nots_found_in_production;
03510 nots_found_in_production = new_not;
03511 new_not->s1 = right_sym;
03512 symbol_add_ref(right_sym);
03513 new_not->s2 = referent;
03514 symbol_add_ref(referent);
03515 continue;
03516 }
03517
03518 if (rt->type == VARIABLE_RELATIONAL_RETE_TEST + RELATIONAL_NOT_EQUAL_RETE_TEST) {
03519 referent = var_bound_in_reconstructed_conds(cond,
03520 rt->data.variable_referent.field_num,
03521 rt->data.variable_referent.levels_up);
03522 if (referent->common.symbol_type != IDENTIFIER_SYMBOL_TYPE)
03523 continue;
03524 allocate_with_pool(¤t_agent(not_pool), &new_not);
03525 new_not->next = nots_found_in_production;
03526 nots_found_in_production = new_not;
03527 new_not->s1 = right_sym;
03528 symbol_add_ref(right_sym);
03529 new_not->s2 = referent;
03530 symbol_add_ref(referent);
03531 continue;
03532 }
03533 }
03534 }
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545 void add_varnames_to_test(varnames * vn, test * t)
03546 {
03547 test new;
03548 cons *c;
03549
03550 if (vn == NIL)
03551 return;
03552 if (varnames_is_one_var(vn)) {
03553 new = make_equality_test(varnames_to_one_var(vn));
03554 add_new_test_to_test(t, new);
03555 } else {
03556 for (c = varnames_to_var_list(vn); c != NIL; c = c->rest) {
03557 new = make_equality_test((Symbol *) (c->first));
03558 add_new_test_to_test(t, new);
03559 }
03560 }
03561 }
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571 void add_hash_info_to_id_test(condition * cond, byte field_num, rete_node_level levels_up)
03572 {
03573 Symbol *temp;
03574 test new;
03575
03576 temp = var_bound_in_reconstructed_conds(cond, field_num, levels_up);
03577 new = make_equality_test(temp);
03578 add_new_test_to_test(&(cond->data.tests.id_test), new);
03579 }
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600 void rete_node_to_conditions(rete_node * node,
03601 node_varnames * nvn,
03602 rete_node * cutoff,
03603 token * tok,
03604 wme * w,
03605 condition * conds_for_cutoff_and_up,
03606 condition ** dest_top_cond, condition ** dest_bottom_cond)
03607 {
03608 condition *cond;
03609 alpha_mem *am;
03610
03611 allocate_with_pool(¤t_agent(condition_pool), &cond);
03612 if (real_parent_node(node) == cutoff) {
03613 cond->prev = conds_for_cutoff_and_up;
03614
03615 *dest_top_cond = cond;
03616 } else {
03617 rete_node_to_conditions(real_parent_node(node),
03618 nvn ? nvn->parent : NIL,
03619 cutoff,
03620 tok ? tok->parent : NIL,
03621 tok ? tok->w : NIL, conds_for_cutoff_and_up, dest_top_cond, &(cond->prev));
03622 cond->prev->next = cond;
03623 }
03624 cond->next = NIL;
03625 *dest_bottom_cond = cond;
03626
03627 if (node->node_type == CN_BNODE) {
03628 cond->type = CONJUNCTIVE_NEGATION_CONDITION;
03629 rete_node_to_conditions(node->b.cn.partner->parent,
03630 nvn ? nvn->data.bottom_of_subconditions : NIL,
03631 node->parent, NIL, NIL, cond->prev, &(cond->data.ncc.top), &(cond->data.ncc.bottom));
03632 cond->data.ncc.top->prev = NIL;
03633 } else {
03634 if (bnode_is_positive(node->node_type))
03635 cond->type = POSITIVE_CONDITION;
03636 else
03637 cond->type = NEGATIVE_CONDITION;
03638
03639 if (w && (cond->type == POSITIVE_CONDITION)) {
03640
03641 cond->data.tests.id_test = make_equality_test(w->id);
03642 cond->data.tests.attr_test = make_equality_test(w->attr);
03643 cond->data.tests.value_test = make_equality_test(w->value);
03644 cond->test_for_acceptable_preference = w->acceptable;
03645 cond->bt.wme = w;
03646 if (node->b.posneg.other_tests)
03647 collect_nots(node->b.posneg.other_tests, w, cond);
03648 } else {
03649 am = node->b.posneg.alpha_mem;
03650 cond->data.tests.id_test = make_blank_or_equality_test(am->id);
03651 cond->data.tests.attr_test = make_blank_or_equality_test(am->attr);
03652 cond->data.tests.value_test = make_blank_or_equality_test(am->value);
03653 cond->test_for_acceptable_preference = am->acceptable;
03654
03655 if (nvn) {
03656 add_varnames_to_test(nvn->data.fields.id_varnames, &(cond->data.tests.id_test));
03657 add_varnames_to_test(nvn->data.fields.attr_varnames, &(cond->data.tests.attr_test));
03658 add_varnames_to_test(nvn->data.fields.value_varnames, &(cond->data.tests.value_test));
03659 }
03660
03661
03662 if ((node->node_type == MP_BNODE) || (node->node_type == NEGATIVE_BNODE)) {
03663 add_hash_info_to_id_test(cond, node->left_hash_loc_field_num, node->left_hash_loc_levels_up);
03664 } else if (node->node_type == POSITIVE_BNODE) {
03665 add_hash_info_to_id_test(cond,
03666 node->parent->left_hash_loc_field_num, node->parent->left_hash_loc_levels_up);
03667 }
03668
03669
03670 if (node->b.posneg.other_tests)
03671 add_rete_test_list_to_tests(cond, node->b.posneg.other_tests);
03672
03673
03674
03675 if (!nvn) {
03676 if (!test_includes_equality_test_for_symbol(cond->data.tests.id_test, NIL))
03677 add_gensymmed_equality_test(&(cond->data.tests.id_test), 's');
03678 if (!test_includes_equality_test_for_symbol(cond->data.tests.attr_test, NIL))
03679 add_gensymmed_equality_test(&(cond->data.tests.attr_test), 'a');
03680 if (!test_includes_equality_test_for_symbol(cond->data.tests.value_test, NIL))
03681 add_gensymmed_equality_test(&(cond->data.tests.value_test),
03682 first_letter_from_test(cond->data.tests.attr_test));
03683 }
03684 }
03685 }
03686 }
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700 long highest_rhs_unboundvar_index;
03701
03702 rhs_value copy_rhs_value_and_substitute_varnames(rhs_value rv, condition * cond, char first_letter)
03703 {
03704 cons *c, *new_c, *prev_new_c;
03705 list *fl, *new_fl;
03706 Symbol *sym;
03707 long index;
03708 char prefix[2];
03709
03710 if (rhs_value_is_reteloc(rv)) {
03711 sym = var_bound_in_reconstructed_conds(cond,
03712 (byte) rhs_value_to_reteloc_field_num(rv),
03713 (rete_node_level) rhs_value_to_reteloc_levels_up(rv));
03714 symbol_add_ref(sym);
03715 return symbol_to_rhs_value(sym);
03716 }
03717
03718 if (rhs_value_is_unboundvar(rv)) {
03719 index = rhs_value_to_unboundvar(rv);
03720 if (!*(current_agent(rhs_variable_bindings) + index)) {
03721 prefix[0] = first_letter;
03722 prefix[1] = 0;
03723 sym = generate_new_variable(prefix);
03724 *(current_agent(rhs_variable_bindings) + index) = sym;
03725 if (highest_rhs_unboundvar_index < index)
03726 highest_rhs_unboundvar_index = index;
03727 } else {
03728 sym = *(current_agent(rhs_variable_bindings) + index);
03729 symbol_add_ref(sym);
03730 }
03731 return symbol_to_rhs_value(sym);
03732 }
03733
03734 if (rhs_value_is_funcall(rv)) {
03735 fl = rhs_value_to_funcall_list(rv);
03736 allocate_cons(&new_fl);
03737 new_fl->first = fl->first;
03738 prev_new_c = new_fl;
03739 for (c = fl->rest; c != NIL; c = c->rest) {
03740 allocate_cons(&new_c);
03741 new_c->first = copy_rhs_value_and_substitute_varnames(c->first, cond, first_letter);
03742 prev_new_c->rest = new_c;
03743 prev_new_c = new_c;
03744 }
03745 prev_new_c->rest = NIL;
03746 return funcall_list_to_rhs_value(new_fl);
03747 } else {
03748 symbol_add_ref(rhs_value_to_symbol(rv));
03749 return rv;
03750 }
03751 }
03752
03753 action *copy_action_list_and_substitute_varnames(action * actions, condition * cond)
03754 {
03755 action *old, *new, *prev, *first;
03756 char first_letter;
03757
03758 prev = NIL;
03759 first = NIL;
03760 old = actions;
03761 while (old) {
03762 allocate_with_pool(¤t_agent(action_pool), &new);
03763 if (prev)
03764 prev->next = new;
03765 else
03766 first = new;
03767 prev = new;
03768 new->type = old->type;
03769 new->preference_type = old->preference_type;
03770 new->support = old->support;
03771 if (old->type == FUNCALL_ACTION) {
03772 new->value = copy_rhs_value_and_substitute_varnames(old->value, cond, 'v');
03773 } else {
03774 new->id = copy_rhs_value_and_substitute_varnames(old->id, cond, 's');
03775 new->attr = copy_rhs_value_and_substitute_varnames(old->attr, cond, 'a');
03776 first_letter = first_letter_from_rhs_value(new->attr);
03777 new->value = copy_rhs_value_and_substitute_varnames(old->value, cond, first_letter);
03778 if (preference_is_binary(old->preference_type))
03779 new->referent = copy_rhs_value_and_substitute_varnames(old->referent, cond, first_letter);
03780 }
03781 old = old->next;
03782 }
03783 if (prev)
03784 prev->next = NIL;
03785 else
03786 first = NIL;
03787 return first;
03788 }
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807 void p_node_to_conditions_and_nots(rete_node * p_node,
03808 token * tok,
03809 wme * w,
03810 condition ** dest_top_cond,
03811 condition ** dest_bottom_cond, not ** dest_nots, action ** dest_rhs)
03812 {
03813 cons *c;
03814 Symbol **cell;
03815 long index;
03816 production *prod;
03817
03818 prod = p_node->b.p.prod;
03819
03820 nots_found_in_production = NIL;
03821 if (tok == NIL)
03822 w = NIL;
03823 reset_variable_generator(NIL, NIL);
03824 rete_node_to_conditions(p_node->parent,
03825 p_node->b.p.parents_nvn,
03826 current_agent(dummy_top_node), tok, w, NIL, dest_top_cond, dest_bottom_cond);
03827 if (tok)
03828 *dest_nots = nots_found_in_production;
03829 nots_found_in_production = NIL;
03830 if (dest_rhs) {
03831 highest_rhs_unboundvar_index = -1;
03832 if (prod->rhs_unbound_variables) {
03833 cell = current_agent(rhs_variable_bindings);
03834 for (c = prod->rhs_unbound_variables; c != NIL; c = c->rest) {
03835 *(cell++) = c->first;
03836 highest_rhs_unboundvar_index++;
03837 }
03838 }
03839 *dest_rhs = copy_action_list_and_substitute_varnames(prod->action_list, *dest_bottom_cond);
03840 index = 0;
03841 cell = current_agent(rhs_variable_bindings);
03842 while (index++ <= highest_rhs_unboundvar_index)
03843 *(cell++) = NIL;
03844 }
03845 }
03846
03847 Symbol *get_symbol_from_rete_loc(unsigned short levels_up, byte field_num, token * tok, wme * w)
03848 {
03849 while (levels_up) {
03850 levels_up--;
03851 w = tok->w;
03852 tok = tok->parent;
03853 }
03854 if (field_num == 0)
03855 return w->id;
03856 if (field_num == 1)
03857 return w->attr;
03858 return w->value;
03859 }
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871 bool((*(rete_test_routines[256]))
03872 (rete_test * rt, token * left, wme * w));
03873
03874 #define match_left_and_right(rete_test,left,w) \
03875 ( (*(rete_test_routines[(rete_test)->type])) \
03876 ((rete_test),(left),(w)) )
03877
03878 #define numeric_comparison_between_symbols(s1,s2,comparator_op) ( \
03879 ( ((s1)->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) && \
03880 ((s2)->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) ) ? \
03881 (((s1)->ic.value) comparator_op ((s2)->ic.value)) : \
03882 ( ((s1)->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) && \
03883 ((s2)->common.symbol_type==FLOAT_CONSTANT_SYMBOL_TYPE) ) ? \
03884 (((s1)->ic.value) comparator_op ((s2)->fc.value)) : \
03885 ( ((s1)->common.symbol_type==FLOAT_CONSTANT_SYMBOL_TYPE) && \
03886 ((s2)->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) ) ? \
03887 (((s1)->fc.value) comparator_op ((s2)->ic.value)) : \
03888 ( ((s1)->common.symbol_type==FLOAT_CONSTANT_SYMBOL_TYPE) && \
03889 ((s2)->common.symbol_type==FLOAT_CONSTANT_SYMBOL_TYPE) ) ? \
03890 (((s1)->fc.value) comparator_op ((s2)->fc.value)) : \
03891 FALSE )
03892
03893
03894
03895
03896 bool error_rete_test_routine(rete_test * rt, token * left, wme * w)
03897 {
03898
03899 char msg[MESSAGE_SIZE];
03900 strncpy(msg, "Internal error: bad rete test type, hit error_rete_test_routine\n", MESSAGE_SIZE);
03901 msg[MESSAGE_SIZE - 1] = 0;
03902 abort_with_fatal_error(msg);
03903
03904 rt = rt;
03905 left = left;
03906 w = w;
03907 return FALSE;
03908 }
03909
03910 bool id_is_goal_rete_test_routine(rete_test * rt, token * left, wme * w)
03911 {
03912 rt = rt;
03913 left = left;
03914
03915 return w->id->id.isa_goal;
03916 }
03917
03918 bool id_is_impasse_rete_test_routine(rete_test * rt, token * left, wme * w)
03919 {
03920
03921 left = left;
03922 rt = rt;
03923
03924 return w->id->id.isa_impasse;
03925 }
03926
03927 bool disjunction_rete_test_routine(rete_test * rt, token * left, wme * w)
03928 {
03929 Symbol *sym;
03930 cons *c;
03931
03932 left = left;
03933
03934 sym = field_from_wme(w, rt->right_field_num);
03935 for (c = rt->data.disjunction_list; c != NIL; c = c->rest)
03936 if (c->first == sym)
03937 return TRUE;
03938 return FALSE;
03939 }
03940
03941 bool constant_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
03942 {
03943 Symbol *s1, *s2;
03944
03945 left = left;
03946
03947 s1 = field_from_wme(w, rt->right_field_num);
03948 s2 = rt->data.constant_referent;
03949 return (bool) (s1 == s2);
03950 }
03951
03952 bool constant_not_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
03953 {
03954 Symbol *s1, *s2;
03955
03956 left = left;
03957
03958 s1 = field_from_wme(w, rt->right_field_num);
03959 s2 = rt->data.constant_referent;
03960 return (bool) (s1 != s2);
03961 }
03962
03963 bool constant_less_rete_test_routine(rete_test * rt, token * left, wme * w)
03964 {
03965 Symbol *s1, *s2;
03966
03967 left = left;
03968
03969 s1 = field_from_wme(w, rt->right_field_num);
03970 s2 = rt->data.constant_referent;
03971 return (bool) numeric_comparison_between_symbols(s1, s2, <);
03972 }
03973
03974 bool constant_greater_rete_test_routine(rete_test * rt, token * left, wme * w)
03975 {
03976 Symbol *s1, *s2;
03977
03978 left = left;
03979
03980 s1 = field_from_wme(w, rt->right_field_num);
03981 s2 = rt->data.constant_referent;
03982 return (bool) numeric_comparison_between_symbols(s1, s2, >);
03983 }
03984
03985 bool constant_less_or_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
03986 {
03987 Symbol *s1, *s2;
03988
03989 left = left;
03990
03991 s1 = field_from_wme(w, rt->right_field_num);
03992 s2 = rt->data.constant_referent;
03993 return (bool) numeric_comparison_between_symbols(s1, s2, <=);
03994 }
03995
03996 bool constant_greater_or_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
03997 {
03998 Symbol *s1, *s2;
03999
04000 left = left;
04001
04002 s1 = field_from_wme(w, rt->right_field_num);
04003 s2 = rt->data.constant_referent;
04004 return (bool) numeric_comparison_between_symbols(s1, s2, >=);
04005 }
04006
04007 bool constant_same_type_rete_test_routine(rete_test * rt, token * left, wme * w)
04008 {
04009 Symbol *s1, *s2;
04010
04011 left = left;
04012
04013 s1 = field_from_wme(w, rt->right_field_num);
04014 s2 = rt->data.constant_referent;
04015 return (bool) (s1->common.symbol_type == s2->common.symbol_type);
04016 }
04017
04018 bool variable_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
04019 {
04020 Symbol *s1, *s2;
04021 int i;
04022
04023 s1 = field_from_wme(w, rt->right_field_num);
04024
04025 if (rt->data.variable_referent.levels_up != 0) {
04026 i = rt->data.variable_referent.levels_up - 1;
04027 while (i != 0) {
04028 left = left->parent;
04029 i--;
04030 }
04031 w = left->w;
04032 }
04033 s2 = field_from_wme(w, rt->data.variable_referent.field_num);
04034
04035 return (bool) (s1 == s2);
04036 }
04037
04038 bool variable_not_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
04039 {
04040 Symbol *s1, *s2;
04041 int i;
04042
04043 s1 = field_from_wme(w, rt->right_field_num);
04044
04045 if (rt->data.variable_referent.levels_up != 0) {
04046 i = rt->data.variable_referent.levels_up - 1;
04047 while (i != 0) {
04048 left = left->parent;
04049 i--;
04050 }
04051 w = left->w;
04052 }
04053 s2 = field_from_wme(w, rt->data.variable_referent.field_num);
04054
04055 return (bool) (s1 != s2);
04056 }
04057
04058 bool variable_less_rete_test_routine(rete_test * rt, token * left, wme * w)
04059 {
04060 Symbol *s1, *s2;
04061 int i;
04062
04063 s1 = field_from_wme(w, rt->right_field_num);
04064
04065 if (rt->data.variable_referent.levels_up != 0) {
04066 i = rt->data.variable_referent.levels_up - 1;
04067 while (i != 0) {
04068 left = left->parent;
04069 i--;
04070 }
04071 w = left->w;
04072 }
04073 s2 = field_from_wme(w, rt->data.variable_referent.field_num);
04074
04075 return (bool) numeric_comparison_between_symbols(s1, s2, <);
04076 }
04077
04078 bool variable_greater_rete_test_routine(rete_test * rt, token * left, wme * w)
04079 {
04080 Symbol *s1, *s2;
04081 int i;
04082
04083 s1 = field_from_wme(w, rt->right_field_num);
04084
04085 if (rt->data.variable_referent.levels_up != 0) {
04086 i = rt->data.variable_referent.levels_up - 1;
04087 while (i != 0) {
04088 left = left->parent;
04089 i--;
04090 }
04091 w = left->w;
04092 }
04093 s2 = field_from_wme(w, rt->data.variable_referent.field_num);
04094
04095 return (bool) numeric_comparison_between_symbols(s1, s2, >);
04096 }
04097
04098 bool variable_less_or_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
04099 {
04100 Symbol *s1, *s2;
04101 int i;
04102
04103 s1 = field_from_wme(w, rt->right_field_num);
04104
04105 if (rt->data.variable_referent.levels_up != 0) {
04106 i = rt->data.variable_referent.levels_up - 1;
04107 while (i != 0) {
04108 left = left->parent;
04109 i--;
04110 }
04111 w = left->w;
04112 }
04113 s2 = field_from_wme(w, rt->data.variable_referent.field_num);
04114
04115 return (bool) numeric_comparison_between_symbols(s1, s2, <=);
04116 }
04117
04118 bool variable_greater_or_equal_rete_test_routine(rete_test * rt, token * left, wme * w)
04119 {
04120 Symbol *s1, *s2;
04121 int i;
04122
04123 s1 = field_from_wme(w, rt->right_field_num);
04124
04125 if (rt->data.variable_referent.levels_up != 0) {
04126 i = rt->data.variable_referent.levels_up - 1;
04127 while (i != 0) {
04128 left = left->parent;
04129 i--;
04130 }
04131 w = left->w;
04132 }
04133 s2 = field_from_wme(w, rt->data.variable_referent.field_num);
04134
04135 return (bool) numeric_comparison_between_symbols(s1, s2, >=);
04136 }
04137
04138 bool variable_same_type_rete_test_routine(rete_test * rt, token * left, wme * w)
04139 {
04140 Symbol *s1, *s2;
04141 int i;
04142
04143 s1 = field_from_wme(w, rt->right_field_num);
04144
04145 if (rt->data.variable_referent.levels_up != 0) {
04146 i = rt->data.variable_referent.levels_up - 1;
04147 while (i != 0) {
04148 left = left->parent;
04149 i--;
04150 }
04151 w = left->w;
04152 }
04153 s2 = field_from_wme(w, rt->data.variable_referent.field_num);
04154 return (bool) (s1->common.symbol_type == s2->common.symbol_type);
04155 }
04156
04157
04158
04159
04160
04161
04162
04163 void positive_node_left_addition(rete_node * node, token * new, Symbol * hash_referent);
04164 void unhashed_positive_node_left_addition(rete_node * node, token * new);
04165
04166 void rete_error_left(rete_node * node, token * t, wme * w)
04167 {
04168 char msg[MESSAGE_SIZE];
04169
04170 w = w;
04171 t = t;
04172
04173 snprintf(msg, MESSAGE_SIZE, "Rete net error: tried to left-activate node of type %d\n", node->node_type);
04174 msg[MESSAGE_SIZE - 1] = 0;
04175 abort_with_fatal_error(msg);
04176 }
04177
04178 void rete_error_right(rete_node * node, wme * w)
04179 {
04180 char msg[MESSAGE_SIZE];
04181
04182 w = w;
04183
04184 snprintf(msg, MESSAGE_SIZE, "Rete net error: tried to right-activate node of type %d\n", node->node_type);
04185 msg[MESSAGE_SIZE - 1] = 0;
04186 abort_with_fatal_error(msg);
04187 }
04188
04189 void beta_memory_node_left_addition(rete_node * node, token * tok, wme * w)
04190 {
04191 unsigned long hv;
04192 Symbol *referent;
04193 rete_node *child, *next;
04194 token *new;
04195
04196 activation_entry_sanity_check();
04197 left_node_activation(node, TRUE);
04198
04199 {
04200 int levels_up;
04201 token *t;
04202
04203 levels_up = node->left_hash_loc_levels_up;
04204 if (levels_up == 1) {
04205 referent = field_from_wme(w, node->left_hash_loc_field_num);
04206 } else {
04207 for (t = tok, levels_up -= 2; levels_up != 0; levels_up--)
04208 t = t->parent;
04209 referent = field_from_wme(t->w, node->left_hash_loc_field_num);
04210 }
04211 }
04212
04213 hv = node->node_id ^ referent->common.hash_id;
04214
04215
04216 token_added(node);
04217 allocate_with_pool(¤t_agent(token_pool), &new);
04218 new_left_token(new, node, tok, w);
04219 insert_token_into_left_ht(new, hv);
04220 new->a.ht.referent = referent;
04221
04222
04223 for (child = node->b.mem.first_linked_child; child != NIL; child = next) {
04224 next = child->a.pos.next_from_beta_mem;
04225 positive_node_left_addition(child, new, referent);
04226 }
04227 activation_exit_sanity_check();
04228 }
04229
04230 void unhashed_beta_memory_node_left_addition(rete_node * node, token * tok, wme * w)
04231 {
04232 unsigned long hv;
04233 rete_node *child, *next;
04234 token *new;
04235
04236 activation_entry_sanity_check();
04237 left_node_activation(node, TRUE);
04238
04239 hv = node->node_id;
04240
04241
04242 token_added(node);
04243 allocate_with_pool(¤t_agent(token_pool), &new);
04244 new_left_token(new, node, tok, w);
04245 insert_token_into_left_ht(new, hv);
04246 new->a.ht.referent = NIL;
04247
04248
04249 for (child = node->b.mem.first_linked_child; child != NIL; child = next) {
04250 next = child->a.pos.next_from_beta_mem;
04251 unhashed_positive_node_left_addition(child, new);
04252 }
04253 activation_exit_sanity_check();
04254 }
04255
04256 void positive_node_left_addition(rete_node * node, token * new, Symbol * hash_referent)
04257 {
04258 unsigned long right_hv;
04259 right_mem *rm;
04260 alpha_mem *am;
04261 rete_test *rt;
04262 bool failed_a_test;
04263 rete_node *child;
04264
04265 activation_entry_sanity_check();
04266 left_node_activation(node, TRUE);
04267
04268 am = node->b.posneg.alpha_mem;
04269
04270 if (node_is_right_unlinked(node)) {
04271 relink_to_right_mem(node);
04272 if (am->right_mems == NIL) {
04273 unlink_from_left_mem(node);
04274 activation_exit_sanity_check();
04275 return;
04276 }
04277 }
04278
04279
04280 right_hv = am->am_id ^ hash_referent->common.hash_id;
04281 for (rm = right_ht_bucket(right_hv); rm != NIL; rm = rm->next_in_bucket) {
04282 if (rm->am != am)
04283 continue;
04284
04285 if (hash_referent != rm->w->id)
04286 continue;
04287 failed_a_test = FALSE;
04288 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04289 if (!match_left_and_right(rt, new, rm->w)) {
04290 failed_a_test = TRUE;
04291 break;
04292 }
04293 if (failed_a_test)
04294 continue;
04295
04296 for (child = node->first_child; child != NIL; child = child->next_sibling)
04297 (*(left_addition_routines[child->node_type])) (child, new, rm->w);
04298 }
04299 activation_exit_sanity_check();
04300 }
04301
04302 void unhashed_positive_node_left_addition(rete_node * node, token * new)
04303 {
04304 right_mem *rm;
04305 rete_test *rt;
04306 bool failed_a_test;
04307 rete_node *child;
04308
04309 activation_entry_sanity_check();
04310 left_node_activation(node, TRUE);
04311
04312 if (node_is_right_unlinked(node)) {
04313 relink_to_right_mem(node);
04314 if (node->b.posneg.alpha_mem->right_mems == NIL) {
04315 unlink_from_left_mem(node);
04316 activation_exit_sanity_check();
04317 return;
04318 }
04319 }
04320
04321
04322 for (rm = node->b.posneg.alpha_mem->right_mems; rm != NIL; rm = rm->next_in_am) {
04323
04324 failed_a_test = FALSE;
04325 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04326 if (!match_left_and_right(rt, new, rm->w)) {
04327 failed_a_test = TRUE;
04328 break;
04329 }
04330 if (failed_a_test)
04331 continue;
04332
04333 for (child = node->first_child; child != NIL; child = child->next_sibling)
04334 (*(left_addition_routines[child->node_type])) (child, new, rm->w);
04335 }
04336 activation_exit_sanity_check();
04337 }
04338
04339 void mp_node_left_addition(rete_node * node, token * tok, wme * w)
04340 {
04341 unsigned long hv;
04342 Symbol *referent;
04343 rete_node *child;
04344 token *new;
04345 unsigned long right_hv;
04346 right_mem *rm;
04347 alpha_mem *am;
04348 rete_test *rt;
04349 bool failed_a_test;
04350
04351 activation_entry_sanity_check();
04352 left_node_activation(node, TRUE);
04353
04354 {
04355 int levels_up;
04356 token *t;
04357
04358 levels_up = node->left_hash_loc_levels_up;
04359 if (levels_up == 1) {
04360 referent = field_from_wme(w, node->left_hash_loc_field_num);
04361 } else {
04362 for (t = tok, levels_up -= 2; levels_up != 0; levels_up--)
04363 t = t->parent;
04364 referent = field_from_wme(t->w, node->left_hash_loc_field_num);
04365 }
04366 }
04367
04368 hv = node->node_id ^ referent->common.hash_id;
04369
04370
04371 token_added(node);
04372 allocate_with_pool(¤t_agent(token_pool), &new);
04373 new_left_token(new, node, tok, w);
04374 insert_token_into_left_ht(new, hv);
04375 new->a.ht.referent = referent;
04376
04377 if (mp_bnode_is_left_unlinked(node)) {
04378 activation_exit_sanity_check();
04379 return;
04380 }
04381
04382 am = node->b.posneg.alpha_mem;
04383
04384 if (node_is_right_unlinked(node)) {
04385 relink_to_right_mem(node);
04386 if (am->right_mems == NIL) {
04387 make_mp_bnode_left_unlinked(node);
04388 activation_exit_sanity_check();
04389 return;
04390 }
04391 }
04392
04393
04394 right_hv = am->am_id ^ referent->common.hash_id;
04395 for (rm = right_ht_bucket(right_hv); rm != NIL; rm = rm->next_in_bucket) {
04396 if (rm->am != am)
04397 continue;
04398
04399 if (referent != rm->w->id)
04400 continue;
04401 failed_a_test = FALSE;
04402 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04403 if (!match_left_and_right(rt, new, rm->w)) {
04404 failed_a_test = TRUE;
04405 break;
04406 }
04407 if (failed_a_test)
04408 continue;
04409
04410 for (child = node->first_child; child != NIL; child = child->next_sibling)
04411 (*(left_addition_routines[child->node_type])) (child, new, rm->w);
04412 }
04413 activation_exit_sanity_check();
04414 }
04415
04416 void unhashed_mp_node_left_addition(rete_node * node, token * tok, wme * w)
04417 {
04418 unsigned long hv;
04419 rete_node *child;
04420 token *new;
04421 right_mem *rm;
04422 rete_test *rt;
04423 bool failed_a_test;
04424
04425 activation_entry_sanity_check();
04426 left_node_activation(node, TRUE);
04427
04428 hv = node->node_id;
04429
04430
04431 token_added(node);
04432 allocate_with_pool(¤t_agent(token_pool), &new);
04433 new_left_token(new, node, tok, w);
04434 insert_token_into_left_ht(new, hv);
04435 new->a.ht.referent = NIL;
04436
04437 if (mp_bnode_is_left_unlinked(node))
04438 return;
04439
04440 if (node_is_right_unlinked(node)) {
04441 relink_to_right_mem(node);
04442 if (node->b.posneg.alpha_mem->right_mems == NIL) {
04443 make_mp_bnode_left_unlinked(node);
04444 activation_exit_sanity_check();
04445 return;
04446 }
04447 }
04448
04449
04450 for (rm = node->b.posneg.alpha_mem->right_mems; rm != NIL; rm = rm->next_in_am) {
04451
04452 failed_a_test = FALSE;
04453 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04454 if (!match_left_and_right(rt, new, rm->w)) {
04455 failed_a_test = TRUE;
04456 break;
04457 }
04458 if (failed_a_test)
04459 continue;
04460
04461 for (child = node->first_child; child != NIL; child = child->next_sibling)
04462 (*(left_addition_routines[child->node_type])) (child, new, rm->w);
04463 }
04464 activation_exit_sanity_check();
04465 }
04466
04467 void positive_node_right_addition(rete_node * node, wme * w)
04468 {
04469 unsigned long hv;
04470 token *tok;
04471 Symbol *referent;
04472 rete_test *rt;
04473 bool failed_a_test;
04474 rete_node *child;
04475
04476 activation_entry_sanity_check();
04477 right_node_activation(node, TRUE);
04478
04479 if (node_is_left_unlinked(node)) {
04480 relink_to_left_mem(node);
04481 if (!node->parent->a.np.tokens) {
04482 unlink_from_right_mem(node);
04483 activation_exit_sanity_check();
04484 return;
04485 }
04486 }
04487
04488 referent = w->id;
04489 hv = node->parent->node_id ^ referent->common.hash_id;
04490
04491 for (tok = left_ht_bucket(hv); tok != NIL; tok = tok->a.ht.next_in_bucket) {
04492 if (tok->node != node->parent)
04493 continue;
04494
04495 if (tok->a.ht.referent != referent)
04496 continue;
04497 failed_a_test = FALSE;
04498 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04499 if (!match_left_and_right(rt, tok, w)) {
04500 failed_a_test = TRUE;
04501 break;
04502 }
04503 if (failed_a_test)
04504 continue;
04505
04506 for (child = node->first_child; child != NIL; child = child->next_sibling)
04507 (*(left_addition_routines[child->node_type])) (child, tok, w);
04508 }
04509 activation_exit_sanity_check();
04510 }
04511
04512 void unhashed_positive_node_right_addition(rete_node * node, wme * w)
04513 {
04514 unsigned long hv;
04515 token *tok;
04516 rete_test *rt;
04517 bool failed_a_test;
04518 rete_node *child;
04519
04520 activation_entry_sanity_check();
04521 right_node_activation(node, TRUE);
04522
04523 if (node_is_left_unlinked(node)) {
04524 relink_to_left_mem(node);
04525 if (!node->parent->a.np.tokens) {
04526 unlink_from_right_mem(node);
04527 activation_exit_sanity_check();
04528 return;
04529 }
04530 }
04531
04532 hv = node->parent->node_id;
04533
04534 for (tok = left_ht_bucket(hv); tok != NIL; tok = tok->a.ht.next_in_bucket) {
04535 if (tok->node != node->parent)
04536 continue;
04537
04538 failed_a_test = FALSE;
04539 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04540 if (!match_left_and_right(rt, tok, w)) {
04541 failed_a_test = TRUE;
04542 break;
04543 }
04544 if (failed_a_test)
04545 continue;
04546
04547 for (child = node->first_child; child != NIL; child = child->next_sibling)
04548 (*(left_addition_routines[child->node_type])) (child, tok, w);
04549 }
04550 activation_exit_sanity_check();
04551 }
04552
04553 void mp_node_right_addition(rete_node * node, wme * w)
04554 {
04555 unsigned long hv;
04556 token *tok;
04557 Symbol *referent;
04558 rete_test *rt;
04559 bool failed_a_test;
04560 rete_node *child;
04561
04562 activation_entry_sanity_check();
04563 right_node_activation(node, TRUE);
04564
04565 if (mp_bnode_is_left_unlinked(node)) {
04566 make_mp_bnode_left_linked(node);
04567 if (!node->a.np.tokens) {
04568 unlink_from_right_mem(node);
04569 activation_exit_sanity_check();
04570 return;
04571 }
04572 }
04573
04574 referent = w->id;
04575 hv = node->node_id ^ referent->common.hash_id;
04576
04577 for (tok = left_ht_bucket(hv); tok != NIL; tok = tok->a.ht.next_in_bucket) {
04578 if (tok->node != node)
04579 continue;
04580
04581 if (tok->a.ht.referent != referent)
04582 continue;
04583 failed_a_test = FALSE;
04584 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04585 if (!match_left_and_right(rt, tok, w)) {
04586 failed_a_test = TRUE;
04587 break;
04588 }
04589 if (failed_a_test)
04590 continue;
04591
04592 for (child = node->first_child; child != NIL; child = child->next_sibling)
04593 (*(left_addition_routines[child->node_type])) (child, tok, w);
04594 }
04595 activation_exit_sanity_check();
04596 }
04597
04598 void unhashed_mp_node_right_addition(rete_node * node, wme * w)
04599 {
04600 unsigned long hv;
04601 token *tok;
04602 rete_test *rt;
04603 bool failed_a_test;
04604 rete_node *child;
04605
04606 activation_entry_sanity_check();
04607 right_node_activation(node, TRUE);
04608
04609 if (mp_bnode_is_left_unlinked(node)) {
04610 make_mp_bnode_left_linked(node);
04611 if (!node->a.np.tokens) {
04612 unlink_from_right_mem(node);
04613 activation_exit_sanity_check();
04614 return;
04615 }
04616 }
04617
04618 hv = node->node_id;
04619
04620 for (tok = left_ht_bucket(hv); tok != NIL; tok = tok->a.ht.next_in_bucket) {
04621 if (tok->node != node)
04622 continue;
04623
04624 failed_a_test = FALSE;
04625 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04626 if (!match_left_and_right(rt, tok, w)) {
04627 failed_a_test = TRUE;
04628 break;
04629 }
04630 if (failed_a_test)
04631 continue;
04632
04633 for (child = node->first_child; child != NIL; child = child->next_sibling)
04634 (*(left_addition_routines[child->node_type])) (child, tok, w);
04635 }
04636 activation_exit_sanity_check();
04637 }
04638
04639
04640
04641
04642
04643
04644
04645 void negative_node_left_addition(rete_node * node, token * tok, wme * w)
04646 {
04647 unsigned long hv, right_hv;
04648 Symbol *referent;
04649 right_mem *rm;
04650 alpha_mem *am;
04651 rete_test *rt;
04652 bool failed_a_test;
04653 rete_node *child;
04654 token *new;
04655
04656 activation_entry_sanity_check();
04657 left_node_activation(node, TRUE);
04658
04659 if (node_is_right_unlinked(node))
04660 relink_to_right_mem(node);
04661
04662 {
04663 int levels_up;
04664 token *t;
04665
04666 levels_up = node->left_hash_loc_levels_up;
04667 if (levels_up == 1) {
04668 referent = field_from_wme(w, node->left_hash_loc_field_num);
04669 } else {
04670 for (t = tok, levels_up -= 2; levels_up != 0; levels_up--)
04671 t = t->parent;
04672 referent = field_from_wme(t->w, node->left_hash_loc_field_num);
04673 }
04674 }
04675
04676 hv = node->node_id ^ referent->common.hash_id;
04677
04678
04679 token_added(node);
04680 allocate_with_pool(¤t_agent(token_pool), &new);
04681 new_left_token(new, node, tok, w);
04682 insert_token_into_left_ht(new, hv);
04683 new->a.ht.referent = referent;
04684 new->negrm_tokens = NIL;
04685
04686
04687 am = node->b.posneg.alpha_mem;
04688 right_hv = am->am_id ^ referent->common.hash_id;
04689 for (rm = right_ht_bucket(right_hv); rm != NIL; rm = rm->next_in_bucket) {
04690 if (rm->am != am)
04691 continue;
04692
04693 if (referent != rm->w->id)
04694 continue;
04695 failed_a_test = FALSE;
04696 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04697 if (!match_left_and_right(rt, new, rm->w)) {
04698 failed_a_test = TRUE;
04699 break;
04700 }
04701 if (failed_a_test)
04702 continue;
04703 {
04704 token *t;
04705 allocate_with_pool(¤t_agent(token_pool), &t);
04706 t->node = node;
04707 t->parent = NIL;
04708 t->w = rm->w;
04709 t->a.neg.left_token = new;
04710 insert_at_head_of_dll(rm->w->tokens, t, next_from_wme, prev_from_wme);
04711 t->first_child = NIL;
04712 insert_at_head_of_dll(new->negrm_tokens, t, a.neg.next_negrm, a.neg.prev_negrm);
04713 }
04714 }
04715
04716
04717 if (!new->negrm_tokens) {
04718 for (child = node->first_child; child != NIL; child = child->next_sibling)
04719 (*(left_addition_routines[child->node_type])) (child, new, NIL);
04720 }
04721 activation_exit_sanity_check();
04722 }
04723
04724 void unhashed_negative_node_left_addition(rete_node * node, token * tok, wme * w)
04725 {
04726 unsigned long hv;
04727 rete_test *rt;
04728 bool failed_a_test;
04729 right_mem *rm;
04730 rete_node *child;
04731 token *new;
04732
04733 activation_entry_sanity_check();
04734 left_node_activation(node, TRUE);
04735
04736 if (node_is_right_unlinked(node))
04737 relink_to_right_mem(node);
04738
04739 hv = node->node_id;
04740
04741
04742 token_added(node);
04743 allocate_with_pool(¤t_agent(token_pool), &new);
04744 new_left_token(new, node, tok, w);
04745 insert_token_into_left_ht(new, hv);
04746 new->a.ht.referent = NIL;
04747 new->negrm_tokens = NIL;
04748
04749
04750 for (rm = node->b.posneg.alpha_mem->right_mems; rm != NIL; rm = rm->next_in_am) {
04751
04752 failed_a_test = FALSE;
04753 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04754 if (!match_left_and_right(rt, new, rm->w)) {
04755 failed_a_test = TRUE;
04756 break;
04757 }
04758 if (failed_a_test)
04759 continue;
04760 {
04761 token *t;
04762 allocate_with_pool(¤t_agent(token_pool), &t);
04763 t->node = node;
04764 t->parent = NIL;
04765 t->w = rm->w;
04766 t->a.neg.left_token = new;
04767 insert_at_head_of_dll(rm->w->tokens, t, next_from_wme, prev_from_wme);
04768 t->first_child = NIL;
04769 insert_at_head_of_dll(new->negrm_tokens, t, a.neg.next_negrm, a.neg.prev_negrm);
04770 }
04771 }
04772
04773
04774 if (!new->negrm_tokens) {
04775 for (child = node->first_child; child != NIL; child = child->next_sibling)
04776 (*(left_addition_routines[child->node_type])) (child, new, NIL);
04777 }
04778 activation_exit_sanity_check();
04779 }
04780
04781 void negative_node_right_addition(rete_node * node, wme * w)
04782 {
04783 unsigned long hv;
04784 token *tok;
04785 Symbol *referent;
04786 rete_test *rt;
04787 bool failed_a_test;
04788
04789 activation_entry_sanity_check();
04790 right_node_activation(node, TRUE);
04791
04792 referent = w->id;
04793 hv = node->node_id ^ referent->common.hash_id;
04794
04795 for (tok = left_ht_bucket(hv); tok != NIL; tok = tok->a.ht.next_in_bucket) {
04796 if (tok->node != node)
04797 continue;
04798
04799 if (tok->a.ht.referent != referent)
04800 continue;
04801 failed_a_test = FALSE;
04802 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04803 if (!match_left_and_right(rt, tok, w)) {
04804 failed_a_test = TRUE;
04805 break;
04806 }
04807 if (failed_a_test)
04808 continue;
04809
04810 {
04811 token *t;
04812 allocate_with_pool(¤t_agent(token_pool), &t);
04813 t->node = node;
04814 t->parent = NIL;
04815 t->w = w;
04816 t->a.neg.left_token = tok;
04817 insert_at_head_of_dll(w->tokens, t, next_from_wme, prev_from_wme);
04818 t->first_child = NIL;
04819 insert_at_head_of_dll(tok->negrm_tokens, t, a.neg.next_negrm, a.neg.prev_negrm);
04820 }
04821 while (tok->first_child)
04822 remove_token_and_subtree(tok->first_child);
04823 }
04824 activation_exit_sanity_check();
04825 }
04826
04827 void unhashed_negative_node_right_addition(rete_node * node, wme * w)
04828 {
04829 unsigned long hv;
04830 token *tok;
04831 rete_test *rt;
04832 bool failed_a_test;
04833
04834 activation_entry_sanity_check();
04835 right_node_activation(node, TRUE);
04836
04837 hv = node->node_id;
04838
04839 for (tok = left_ht_bucket(hv); tok != NIL; tok = tok->a.ht.next_in_bucket) {
04840 if (tok->node != node)
04841 continue;
04842
04843 failed_a_test = FALSE;
04844 for (rt = node->b.posneg.other_tests; rt != NIL; rt = rt->next)
04845 if (!match_left_and_right(rt, tok, w)) {
04846 failed_a_test = TRUE;
04847 break;
04848 }
04849 if (failed_a_test)
04850 continue;
04851
04852 {
04853 token *t;
04854 allocate_with_pool(¤t_agent(token_pool), &t);
04855 t->node = node;
04856 t->parent = NIL;
04857 t->w = w;
04858 t->a.neg.left_token = tok;
04859 insert_at_head_of_dll(w->tokens, t, next_from_wme, prev_from_wme);
04860 t->first_child = NIL;
04861 insert_at_head_of_dll(tok->negrm_tokens, t, a.neg.next_negrm, a.neg.prev_negrm);
04862 }
04863 while (tok->first_child)
04864 remove_token_and_subtree(tok->first_child);
04865 }
04866 activation_exit_sanity_check();
04867 }
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878 void cn_node_left_addition(rete_node * node, token * tok, wme * w)
04879 {
04880 unsigned long hv;
04881 token *t, *new;
04882 rete_node *child;
04883
04884 activation_entry_sanity_check();
04885 left_node_activation(node, TRUE);
04886
04887 hv = node->node_id ^ (unsigned long) tok ^ (unsigned long) w;
04888
04889
04890
04891
04892 for (t = left_ht_bucket(hv); t != NIL; t = t->a.ht.next_in_bucket)
04893 if ((t->node == node) && (t->parent == tok) && (t->w == w))
04894 return;
04895
04896
04897 token_added(node);
04898 allocate_with_pool(¤t_agent(token_pool), &new);
04899 new_left_token(new, node, tok, w);
04900 insert_token_into_left_ht(new, hv);
04901 new->negrm_tokens = NIL;
04902
04903
04904 for (child = node->first_child; child != NIL; child = child->next_sibling)
04905 (*(left_addition_routines[child->node_type])) (child, new, NIL);
04906
04907 activation_exit_sanity_check();
04908 }
04909
04910 void cn_partner_node_left_addition(rete_node * node, token * tok, wme * w)
04911 {
04912 rete_node *partner, *temp;
04913 unsigned long hv;
04914 token *left, *negrm_tok;
04915
04916 activation_entry_sanity_check();
04917 left_node_activation(node, TRUE);
04918
04919 partner = node->b.cn.partner;
04920
04921
04922 token_added(node);
04923 allocate_with_pool(¤t_agent(token_pool), &negrm_tok);
04924 new_left_token(negrm_tok, node, tok, w);
04925
04926
04927 temp = node->parent;
04928 while (temp != partner->parent) {
04929 temp = real_parent_node(temp);
04930 w = tok->w;
04931 tok = tok->parent;
04932 }
04933
04934
04935 hv = partner->node_id ^ (unsigned long) tok ^ (unsigned long) w;
04936 for (left = left_ht_bucket(hv); left != NIL; left = left->a.ht.next_in_bucket)
04937 if ((left->node == partner) && (left->parent == tok) && (left->w == w))
04938 break;
04939
04940
04941 if (!left) {
04942 token_added(partner);
04943 allocate_with_pool(¤t_agent(token_pool), &left);
04944 new_left_token(left, partner, tok, w);
04945 insert_token_into_left_ht(left, hv);
04946 left->negrm_tokens = NIL;
04947 }
04948
04949
04950 negrm_tok->a.neg.left_token = left;
04951 insert_at_head_of_dll(left->negrm_tokens, negrm_tok, a.neg.next_negrm, a.neg.prev_negrm);
04952
04953
04954 while (left->first_child)
04955 remove_token_and_subtree(left->first_child);
04956
04957 activation_exit_sanity_check();
04958 }
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991 void p_node_left_addition(rete_node * node, token * tok, wme * w)
04992 {
04993 ms_change *msc;
04994 condition *cond;
04995 token *current_token, *new;
04996 wme *current_wme;
04997 rete_node *current_node;
04998 bool match_found;
04999
05000
05001
05002 int prod_type;
05003 token *OPERAND_curr_tok, *temp_tok;
05004
05005 action *act;
05006 bool operator_proposal, op_elab;
05007 char action_attr[ACTION_ATTR_SIZE];
05008
05009 int pass;
05010 wme *lowest_goal_wme;
05011
05012
05013
05014 activation_entry_sanity_check();
05015 left_node_activation(node, TRUE);
05016
05017
05018 token_added(node);
05019 allocate_with_pool(¤t_agent(token_pool), &new);
05020 new_left_token(new, node, tok, w);
05021
05022
05023 match_found = FALSE;
05024 for (msc = node->b.p.tentative_retractions; msc != NIL; msc = msc->next_of_node) {
05025 match_found = TRUE;
05026 cond = msc->inst->bottom_of_instantiated_conditions;
05027 current_token = tok;
05028 current_wme = w;
05029 current_node = node->parent;
05030 while (current_node->node_type != DUMMY_TOP_BNODE) {
05031 if (bnode_is_positive(current_node->node_type))
05032 if (current_wme != cond->bt.wme) {
05033 match_found = FALSE;
05034 break;
05035 }
05036 current_node = real_parent_node(current_node);
05037 current_wme = current_token->w;
05038 current_token = current_token->parent;
05039 cond = cond->prev;
05040 }
05041 if (match_found)
05042 break;
05043 }
05044
05045 #ifdef BUG_139_WORKAROUND
05046
05047
05048
05049 if (match_found && node->b.p.prod->type == JUSTIFICATION_PRODUCTION_TYPE) {
05050 if (node->b.p.prod->already_fired) {
05051 return;
05052 } else {
05053 node->b.p.prod->already_fired = 1;
05054 }
05055 }
05056 #endif
05057
05058
05059 if (match_found) {
05060 msc->inst->rete_token = tok;
05061 msc->inst->rete_wme = w;
05062
05063 remove_from_dll(node->b.p.tentative_retractions, msc, next_of_node, prev_of_node);
05064 remove_from_dll(current_agent(ms_retractions), msc, next, prev);
05065
05066 if (msc->goal) {
05067 remove_from_dll(msc->goal->id.ms_retractions, msc, next_in_level, prev_in_level);
05068 } else {
05069 remove_from_dll(current_agent(nil_goal_retractions), msc, next_in_level, prev_in_level);
05070 }
05071
05072
05073 free_with_pool(¤t_agent(ms_change_pool), msc);
05074 #ifdef DEBUG_RETE_PNODES
05075 print_with_symbols("\nRemoving tentative retraction: %y", node->b.p.prod->name);
05076 #endif
05077 activation_exit_sanity_check();
05078 return;
05079 }
05080
05081
05082 #ifdef DEBUG_RETE_PNODES
05083 print_with_symbols("\nAdding tentative assertion: %y", node->b.p.prod->name);
05084 #endif
05085
05086 allocate_with_pool(¤t_agent(ms_change_pool), &msc);
05087 msc->tok = tok;
05088 msc->w = w;
05089 msc->p_node = node;
05090 msc->inst = NIL;
05091
05092
05093 msc->level = 0;
05094 msc->goal = NIL;
05095
05096
05097
05098
05099
05100
05101
05102
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116
05117
05118
05119 #ifndef SOAR_8_ONLY
05120 if (current_agent(operand2_mode) == TRUE) {
05121 #endif
05122
05123
05124
05125 msc->goal = find_goal_for_match_set_change_assertion(msc);
05126 msc->level = msc->goal->id.level;
05127 #ifdef DEBUG_WATERFALL
05128 print("\n Level of goal is %d", msc->level);
05129 #endif
05130
05131
05132 prod_type = IE_PRODS;
05133
05134 if (node->b.p.prod->declared_support == DECLARED_O_SUPPORT)
05135 prod_type = PE_PRODS;
05136
05137 else if (node->b.p.prod->declared_support == DECLARED_I_SUPPORT)
05138 prod_type = IE_PRODS;
05139
05140 else if (node->b.p.prod->declared_support == UNDECLARED_SUPPORT) {
05141
05142
05143
05144
05145
05146
05147 operator_proposal = FALSE;
05148
05149 for (act = node->b.p.prod->action_list; act != NIL; act = act->next) {
05150
05151 if ((act->type == MAKE_ACTION) && (rhs_value_is_symbol(act->attr))) {
05152 if ((strcmp(rhs_value_to_string(act->attr, action_attr, ACTION_ATTR_SIZE),
05153 "operator") == NIL) && (act->preference_type == ACCEPTABLE_PREFERENCE_TYPE)) {
05154 operator_proposal = TRUE;
05155 prod_type = !PE_PRODS;
05156 break;
05157 }
05158 }
05159 }
05160
05161 if (operator_proposal == FALSE) {
05162
05163
05164
05165
05166
05167 for (OPERAND_curr_tok = node->a.np.tokens;
05168 OPERAND_curr_tok != NIL; OPERAND_curr_tok = OPERAND_curr_tok->next_of_node) {
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190
05191 op_elab = FALSE;
05192 lowest_goal_wme = NIL;
05193
05194 for (pass = 0; pass != 2; pass++) {
05195
05196 temp_tok = OPERAND_curr_tok;
05197 while (temp_tok != NIL) {
05198 while (temp_tok->w == NIL) {
05199 temp_tok = temp_tok->parent;
05200 if (temp_tok == NIL)
05201 break;
05202 }
05203 if (temp_tok == NIL)
05204 break;
05205 if (temp_tok->w == NIL)
05206 break;
05207
05208 if (pass == 0) {
05209 if (temp_tok->w->id->id.isa_goal == TRUE) {
05210 if (lowest_goal_wme == NIL)
05211 lowest_goal_wme = temp_tok->w;
05212 else {
05213 if (temp_tok->w->id->id.level > lowest_goal_wme->id->id.level)
05214 lowest_goal_wme = temp_tok->w;
05215 }
05216 }
05217 } else {
05218 if ((temp_tok->w->attr ==
05219 current_agent(operator_symbol)) &&
05220 (temp_tok->w->acceptable == FALSE) && (temp_tok->w->id == lowest_goal_wme->id)) {
05221
05222 if (current_agent(o_support_calculation_type) == 3 ||
05223 current_agent(o_support_calculation_type) == 4) {
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234
05235
05236 for (act = node->b.p.prod->action_list; act != NIL; act = act->next) {
05237 if (act->type == MAKE_ACTION) {
05238
05239 if ((rhs_value_is_symbol(act->id)) &&
05243 (rhs_value_to_symbol(act->id) == temp_tok->w->value)) {
05244
05245 op_elab = TRUE;
05246
05247 } else if (current_agent(o_support_calculation_type) == 4 &&
05248 (rhs_value_is_reteloc(act->id)) &&
05249 (temp_tok->w->value ==
05250 get_symbol_from_rete_loc((byte)
05251 rhs_value_to_reteloc_levels_up
05252 (act->id),
05253 (byte)
05254 rhs_value_to_reteloc_field_num
05255 (act->id), tok, w))) {
05256
05257 op_elab = TRUE;
05258
05259 } else {
05260
05261
05262 prod_type = PE_PRODS;
05263 }
05264 }
05265 }
05266 } else {
05267 prod_type = PE_PRODS;
05268 break;
05269 }
05270 }
05271 }
05272 temp_tok = temp_tok->parent;
05273 }
05274
05275 if (prod_type == PE_PRODS) {
05276 if (current_agent(o_support_calculation_type) != 3
05277 && current_agent(o_support_calculation_type != 4)) {
05278 break;
05279 }
05280 } else if (op_elab == TRUE) {
05281
05282
05283
05284 if (current_agent(o_support_calculation_type) == 3 &&
05285 current_agent(sysparams)[PRINT_WARNINGS_SYSPARAM]) {
05286 print_with_symbols
05287 ("\nWARNING: operator elaborations mixed with operator applications\nget o_support in prod %y",
05288 node->b.p.prod->name);
05289 prod_type = PE_PRODS;
05290 break;
05291 } else if (current_agent(o_support_calculation_type) == 4 &&
05292 current_agent(sysparams)[PRINT_WARNINGS_SYSPARAM]) {
05293 print_with_symbols
05294 ("\nWARNING: operator elaborations mixed with operator applications\nget i_support in prod %y",
05295 node->b.p.prod->name);
05296 prod_type = IE_PRODS;
05297 break;
05298 }
05299
05300 }
05301 }
05302 }
05303
05304
05305
05306
05307
05308
05309
05310
05311
05312
05313
05314
05315 }
05316
05317 }
05318
05319
05320 if (prod_type == PE_PRODS) {
05321 insert_at_head_of_dll(current_agent(ms_o_assertions), msc, next, prev);
05322
05323
05324 insert_at_head_of_dll(msc->goal->id.ms_o_assertions, msc, next_in_level, prev_in_level);
05325
05326
05327 node->b.p.prod->OPERAND_which_assert_list = O_LIST;
05328
05329 if (current_agent(soar_verbose_flag) == TRUE) {
05330 print_with_symbols("\n RETE: putting [%y] into ms_o_assertions", node->b.p.prod->name);
05331
05332 }
05333
05334 }
05335
05336 else {
05337 insert_at_head_of_dll(current_agent(ms_i_assertions), msc, next, prev);
05338
05339
05340 insert_at_head_of_dll(msc->goal->id.ms_i_assertions, msc, next_in_level, prev_in_level);
05341
05342
05343 node->b.p.prod->OPERAND_which_assert_list = I_LIST;
05344
05345 if (current_agent(soar_verbose_flag) == TRUE) {
05346 print_with_symbols("\n RETE: putting [%y] into ms_i_assertions", node->b.p.prod->name);
05347
05348 }
05349
05350 }
05351 #ifndef SOAR_8_ONLY
05352 }
05353
05354
05355
05356 else
05357
05358 insert_at_head_of_dll(current_agent(ms_assertions), msc, next, prev);
05359 #endif
05360
05361 #ifdef MATCHTIME_INTERRUPT
05362 if (node->b.p.prod->interrupt) {
05363 char *ch;
05364 node->b.p.prod->interrupt++;
05365 current_agent(stop_soar)++;
05366
05367
05368
05369
05370
05371
05372
05373
05374
05375
05376
05377 strncpy(current_agent(interrupt_source), "*** Interrupt (probably) from production ", INTERRUPT_SOURCE_SIZE);
05378 current_agent(interrupt_source)[INTERRUPT_SOURCE_SIZE - 1] = 0;
05379 ch = current_agent(interrupt_source);
05380 while (*ch)
05381 ch++;
05382 symbol_to_string(node->b.p.prod->name, TRUE, ch,
05383 INTERRUPT_SOURCE_SIZE - (ch - current_agent(interrupt_source)));
05384 while (*ch)
05385 ch++;
05386 strncpy(ch, " ***", INTERRUPT_SOURCE_SIZE - (ch - current_agent(interrupt_source)));
05387 ch[INTERRUPT_SOURCE_SIZE - (ch - current_agent(interrupt_source)) - 1] = 0;
05388 current_agent(reason_for_stopping) = current_agent(interrupt_source);
05389
05390 }
05391 #endif
05392
05393
05394 insert_at_head_of_dll(node->b.p.tentative_assertions, msc, next_of_node, prev_of_node);
05395 activation_exit_sanity_check();
05396 }
05397
05398
05399
05400
05401
05402
05403
05404
05405
05406
05407
05408
05409
05410
05411
05412
05413 void p_node_left_removal(rete_node * node, token * tok, wme * w)
05414 {
05415 ms_change *msc;
05416 instantiation *inst;
05417
05418 activation_entry_sanity_check();
05419
05420
05421 for (msc = node->b.p.tentative_assertions; msc != NIL; msc = msc->next_of_node) {
05422 if ((msc->tok == tok) && (msc->w == w)) {
05423
05424 remove_from_dll(node->b.p.tentative_assertions, msc, next_of_node, prev_of_node);
05425
05426 #ifdef MATCHTIME_INTERRUPT
05427 if (node->b.p.prod->interrupt > 1) {
05428 node->b.p.prod->interrupt--;
05429 current_agent(stop_soar)--;
05430