Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
production.cpp
Go to the documentation of this file.
1 #include <portability.h>
2 
3 /*************************************************************************
4  * PLEASE SEE THE FILE "license.txt" (INCLUDED WITH THIS SOFTWARE PACKAGE)
5  * FOR LICENSE AND COPYRIGHT INFORMATION.
6  *************************************************************************/
7 
8 /*************************************************************************
9  *
10  * file: production.cpp
11  *
12  * ====================================================================
13  * Production Utilities for Soar 6
14  *
15  * This file contains various utility routines for manipulating
16  * productions and parts of productions: tests, conditions, actions,
17  * etc. Also includes the reorderer and compile-time o-support calculations.
18  * parser.cpp loads productions.
19  * Init_production_utilities() should be called before anything else here.
20  * =======================================================================
21  */
22 
23 #include <stdlib.h>
24 
25 #include "production.h"
26 #include "mem.h"
27 #include "kernel.h"
28 #include "print.h"
29 #include "agent.h"
30 #include "gdatastructs.h"
31 #include "rhsfun.h"
32 #include "instantiations.h"
33 #include "reorder.h"
34 #include "symtab.h"
35 #include "init_soar.h"
36 #include "rete.h"
37 #include "utilities.h"
38 #include "reinforcement_learning.h"
39 
40 #include <ctype.h>
41 
42 /* comment out the following line to supress compile-time o-support
43  calculations */
44 /* RCHONG: begin 10.11 */
45 /* #define DO_COMPILE_TIME_O_SUPPORT_CALCS */
46 /* RCHONG: end 10.11 */
47 
48 
49 /* uncomment the following line to get printouts of names of productions
50  that can't be fully compile-time o-support evaluated */
51 /* #define LIST_COMPILE_TIME_O_SUPPORT_FAILURES */
52 
53 void init_production_utilities (agent* thisAgent) {
54  init_memory_pool (thisAgent, &thisAgent->complex_test_pool, sizeof(complex_test), "complex test");
55  init_memory_pool (thisAgent, &thisAgent->condition_pool, sizeof(condition), "condition");
56  init_memory_pool (thisAgent, &thisAgent->production_pool, sizeof(production), "production");
57  init_memory_pool (thisAgent, &thisAgent->action_pool, sizeof(action), "action");
58  init_memory_pool (thisAgent, &thisAgent->not_pool, sizeof(not_struct), "not");
59  init_reorderer(thisAgent);
60 }
61 
62 /* ********************************************************************
63 
64  Utility Routines for Various Parts of Productions
65 
66 ******************************************************************** */
67 
68 /* ====================================================================
69 
70  Utilities for Symbols and Lists of Symbols
71 
72 ==================================================================== */
73 
74 /* -----------------------------------------------------------------
75  First Letter From Symbol
76 
77  When creating dummy variables or identifiers, we try to give them
78  names that start with a "reasonable" letter. For example, ^foo <dummy>
79  becomes ^foo <f*37>, where the variable starts with "f" because
80  the attribute test starts with "f" also. This routine looks at
81  a symbol and tries to figure out a reasonable choice of starting
82  letter for a variable or identifier to follow it. If it can't
83  find a reasonable choice, it returns '*'.
84 ----------------------------------------------------------------- */
85 
87  switch (sym->common.symbol_type) {
88  case VARIABLE_SYMBOL_TYPE: return *(sym->var.name + 1);
89  case IDENTIFIER_SYMBOL_TYPE: return sym->id.name_letter;
90  case SYM_CONSTANT_SYMBOL_TYPE: return *(sym->sc.name);
91  default: return '*';
92  }
93 }
94 
95 /* -----------------------------------------------------------------
96  Find first letter of test, or '*' if nothing appropriate.
97  (See comments on first_letter_from_symbol for more explanation.)
98 ----------------------------------------------------------------- */
99 
101  complex_test *ct;
102  cons *c;
103  char ch;
104 
105  if (test_is_blank_test (t)) return '*';
108 
109  ct = complex_test_from_test (t);
110  switch(ct->type) {
111  case GOAL_ID_TEST: return 's';
112  case IMPASSE_ID_TEST: return 'i';
113  case CONJUNCTIVE_TEST:
114  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest) {
115  ch = first_letter_from_test (static_cast<char *>(c->first));
116  if (ch != '*') return ch;
117  }
118  return '*';
119  default: /* disjunction tests, and relational tests other than equality */
120  return '*';
121  }
122 }
123 
124 /* ----------------------------------------------------------------
125  Takes a list of symbols and returns a copy of the same list,
126  incrementing the reference count on each symbol in the list.
127 ---------------------------------------------------------------- */
128 
130  list *sym_list) {
131  cons *c, *first, *prev;
132 
133  if (! sym_list) return NIL;
134  allocate_cons (thisAgent, &first);
135  first->first = sym_list->first;
136  symbol_add_ref (static_cast<Symbol *>(first->first));
137  sym_list = sym_list->rest;
138  prev = first;
139  while (sym_list) {
140  allocate_cons (thisAgent, &c);
141  prev->rest = c;
142  c->first = sym_list->first;
143  symbol_add_ref (static_cast<Symbol *>(c->first));
144  sym_list = sym_list->rest;
145  prev = c;
146  }
147  prev->rest = NIL;
148  return first;
149 }
150 
151 /* ----------------------------------------------------------------
152  Frees a list of symbols, decrementing their reference counts.
153 ---------------------------------------------------------------- */
154 
156  list *sym_list) {
157  cons *c;
158 
159  while (sym_list) {
160  c = sym_list;
161  sym_list = sym_list->rest;
162  symbol_remove_ref (thisAgent, static_cast<Symbol *>(c->first));
163  free_cons (thisAgent, c);
164  }
165 }
166 
167 /* =================================================================
168 
169  Utility Routines for Tests
170 
171 ================================================================= */
172 
173 /* --- This just copies a consed list of tests. --- */
174 list *copy_test_list (agent* thisAgent, cons *c) {
175  cons *new_c;
176 
177  if (!c) return NIL;
178  allocate_cons (thisAgent, &new_c);
179  new_c->first = copy_test (thisAgent, static_cast<char *>(c->first));
180  new_c->rest = copy_test_list (thisAgent, c->rest);
181  return new_c;
182 }
183 
184 /* ----------------------------------------------------------------
185  Takes a test and returns a new copy of it.
186 ---------------------------------------------------------------- */
187 
188 test copy_test (agent* thisAgent, test t) {
189  Symbol *referent;
190  complex_test *ct, *new_ct;
191 
192  if (test_is_blank_test(t))
193  return make_blank_test();
194 
196  referent = referent_of_equality_test(t);
197  return make_equality_test(referent);
198  }
199 
200  ct = complex_test_from_test(t);
201 
202  allocate_with_pool (thisAgent, &thisAgent->complex_test_pool, &new_ct);
203  new_ct->type = ct->type;
204  switch(ct->type) {
205  case GOAL_ID_TEST:
206  case IMPASSE_ID_TEST:
207  break;
208  case DISJUNCTION_TEST:
209  new_ct->data.disjunction_list =
211  break;
212  case CONJUNCTIVE_TEST:
213  new_ct->data.conjunct_list = copy_test_list (thisAgent, ct->data.conjunct_list);
214  break;
215  default: /* relational tests other than equality */
216  new_ct->data.referent = ct->data.referent;
218  break;
219  }
220  return make_test_from_complex_test(new_ct);
221 }
222 
223 /* ----------------------------------------------------------------
224  Same as copy_test(), only it doesn't include goal or impasse tests
225  in the new copy. The caller should initialize the two flags to FALSE
226  before calling this routine; it sets them to TRUE if it finds a goal
227  or impasse test.
228 ---------------------------------------------------------------- */
229 
231  Bool *removed_goal,
232  Bool *removed_impasse) {
233  complex_test *ct, *new_ct;
234  cons *c;
235  test new_t, temp;
236 
237  if (test_is_blank_or_equality_test(t)) return copy_test (thisAgent, t);
238 
239  ct = complex_test_from_test(t);
240 
241  switch(ct->type) {
242  case GOAL_ID_TEST:
243  *removed_goal = TRUE;
244  return make_blank_test();
245  case IMPASSE_ID_TEST:
246  *removed_impasse = TRUE;
247  return make_blank_test();
248 
249  case CONJUNCTIVE_TEST:
250  new_t = make_blank_test();
251  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest) {
252  temp = copy_test_removing_goal_impasse_tests (thisAgent, static_cast<char *>(c->first),
253  removed_goal,
254  removed_impasse);
255  if (! test_is_blank_test(temp))
256  add_new_test_to_test (thisAgent, &new_t, temp);
257  }
258  if (test_is_complex_test(new_t)) {
259  new_ct = complex_test_from_test(new_t);
260  if (new_ct->type==CONJUNCTIVE_TEST)
261  new_ct->data.conjunct_list =
263  }
264  return new_t;
265 
266  default: /* relational tests other than equality */
267  return copy_test (thisAgent, t);
268  }
269 }
270 
271 /* ----------------------------------------------------------------
272  Deallocates a test.
273 ---------------------------------------------------------------- */
274 
275 void deallocate_test (agent* thisAgent, test t) {
276  cons *c, *next_c;
277  complex_test *ct;
278 
279  if (test_is_blank_test(t)) return;
282  return;
283  }
284 
285  ct = complex_test_from_test(t);
286 
287  switch (ct->type) {
288  case GOAL_ID_TEST:
289  case IMPASSE_ID_TEST:
290  break;
291  case DISJUNCTION_TEST:
293  break;
294  case CONJUNCTIVE_TEST:
295  c = ct->data.conjunct_list;
296  while (c) {
297  next_c = c->rest;
298  deallocate_test (thisAgent, static_cast<char *>(c->first));
299  free_cons (thisAgent, c);
300  c = next_c;
301  }
302  break;
303  default: /* relational tests other than equality */
304  symbol_remove_ref (thisAgent, ct->data.referent);
305  break;
306  }
307  free_with_pool (&thisAgent->complex_test_pool, ct);
308 }
309 
310 /* --- Macro for doing this (usually) without procedure call overhead. --- */
311 #ifdef USE_MACROS
312 #define quickly_deallocate_test(thisAgent, t) { \
313  if (! test_is_blank_test(t)) { \
314  if (test_is_blank_or_equality_test(t)) { \
315  symbol_remove_ref (thisAgent, referent_of_equality_test(t)); \
316  } else { \
317  deallocate_test (thisAgent, t); } } }
318 #else
319 inline void quickly_deallocate_test(agent* thisAgent, test t)
320 {
321  if (! test_is_blank_test(t)) {
323  {
325  }
326  else
327  {
328  deallocate_test (thisAgent, t);
329  }
330  }
331 }
332 #endif
333 
334 /* ----------------------------------------------------------------
335  Destructively modifies the first test (t) by adding the second
336  one (add_me) to it (usually as a new conjunct). The first test
337  need not be a conjunctive test.
338 ---------------------------------------------------------------- */
339 
340 void add_new_test_to_test (agent* thisAgent,
341  test *t, test add_me) {
342  complex_test *ct = 0;
343  cons *c;
344  Bool already_a_conjunctive_test;
345 
346  if (test_is_blank_test(add_me)) return;
347 
348  if (test_is_blank_test(*t)) {
349  *t = add_me;
350  return;
351  }
352 
353  /* --- if *t isn't already a conjunctive test, make it into one --- */
354  already_a_conjunctive_test = FALSE;
355  if (test_is_complex_test(*t)) {
356  ct = complex_test_from_test (*t);
357  if (ct->type==CONJUNCTIVE_TEST) already_a_conjunctive_test = TRUE;
358  }
359 
360  if (! already_a_conjunctive_test) {
361  allocate_with_pool (thisAgent, &thisAgent->complex_test_pool, &ct);
362  ct->type = CONJUNCTIVE_TEST;
363  allocate_cons (thisAgent, &c);
364  ct->data.conjunct_list = c;
365  c->first = *t;
366  c->rest = NIL;
367  *t = make_test_from_complex_test (ct);
368  }
369  /* --- at this point, ct points to the complex test structure for *t --- */
370 
371  /* --- now add add_me to the conjunct list --- */
372  allocate_cons (thisAgent, &c);
373  c->first = add_me;
374  c->rest = ct->data.conjunct_list;
375  ct->data.conjunct_list = c;
376 }
377 
378 /* ----------------------------------------------------------------
379  Same as add_new_test_to_test(), only has no effect if the second
380  test is already included in the first one.
381 ---------------------------------------------------------------- */
382 
383 void add_new_test_to_test_if_not_already_there (agent* thisAgent, test *t, test add_me, bool neg) {
384  complex_test *ct;
385  cons *c;
386 
387  if (tests_are_equal (*t, add_me, neg)) {
388  deallocate_test (thisAgent, add_me);
389  return;
390  }
391 
392  if (test_is_complex_test (*t)) {
393  ct = complex_test_from_test (*t);
394  if (ct->type == CONJUNCTIVE_TEST)
395  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
396  if (tests_are_equal (static_cast<char *>(c->first), add_me, neg)) {
397  deallocate_test (thisAgent, add_me);
398  return;
399  }
400  }
401 
402  add_new_test_to_test (thisAgent, t, add_me);
403 }
404 
405 /* ----------------------------------------------------------------
406  Returns TRUE iff the two tests are identical.
407  If neg is true, ignores order of members in conjunctive tests
408  and assumes variables are all equal.
409 ---------------------------------------------------------------- */
410 
411 Bool tests_are_equal (test t1, test t2, bool neg) {
412  cons *c1, *c2;
413  complex_test *ct1, *ct2;
414 
416  {
418  return FALSE;
419 
420  if (t1 == t2) /* Warning: this relies on the representation of tests */
421  return TRUE;
422 
423  if (!neg)
424  return FALSE;
425 
426  // ignore variables in negation tests
429 
431  {
432  return TRUE;
433  }
434  return FALSE;
435  }
436 
437  ct1 = complex_test_from_test(t1);
438  ct2 = complex_test_from_test(t2);
439 
440  if (ct1->type != ct2->type)
441  return FALSE;
442 
443  switch(ct1->type) {
444  case GOAL_ID_TEST:
445  return TRUE;
446 
447  case IMPASSE_ID_TEST:
448  return TRUE;
449 
450  case DISJUNCTION_TEST:
451  for (c1 = ct1->data.disjunction_list, c2 = ct2->data.disjunction_list; (c1!=NIL) && (c2!=NIL); c1 = c1->rest, c2 = c2->rest)
452  {
453  if (c1->first != c2->first)
454  return FALSE;
455  }
456  if (c1 == c2)
457  return TRUE; /* make sure they both hit end-of-list */
458  return FALSE;
459 
460  case CONJUNCTIVE_TEST:
461  // bug 510 fix: ignore order of test members in conjunctions
462  {
463  std::list<test> copy2;
464  for (c2 = ct2->data.conjunct_list; c2 != NIL; c2 = c2->rest)
465  copy2.push_back(static_cast<test>(c2->first));
466 
467  std::list<test>::iterator iter;
468  for (c1 = ct1->data.conjunct_list; c1 != NIL; c1 = c1->rest)
469  {
470  // check against copy
471  for(iter = copy2.begin(); iter != copy2.end(); ++iter)
472  {
473  if (tests_are_equal(static_cast<test>(c1->first), *iter, neg))
474  break;
475  }
476 
477  // iter will be end if no match
478  if (iter == copy2.end())
479  return FALSE;
480 
481  // there was a match, remove it from unmatched
482  copy2.erase(iter);
483  }
484 
485  // make sure no unmatched remain
486  if (copy2.empty())
487  return TRUE;
488  }
489  return FALSE;
490 
491  default: /* relational tests other than equality */
492  if (ct1->data.referent == ct2->data.referent)
493  return TRUE;
494  return FALSE;
495  }
496 }
497 
498 /* ----------------------------------------------------------------
499  Returns a hash value for the given test.
500 ---------------------------------------------------------------- */
501 
502 uint32_t hash_test (agent* thisAgent, test t) {
503  complex_test *ct;
504  cons *c;
505  uint32_t result;
506 
507  if (test_is_blank_test(t))
508  return 0;
509 
511  return referent_of_equality_test(t)->common.hash_id;
512 
513  ct = complex_test_from_test(t);
514 
515  switch (ct->type) {
516  case GOAL_ID_TEST: return 34894895; /* just use some unusual number */
517  case IMPASSE_ID_TEST: return 2089521;
518  case DISJUNCTION_TEST:
519  result = 7245;
520  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
521  result = result + static_cast<Symbol *>(c->first)->common.hash_id;
522  return result;
523  case CONJUNCTIVE_TEST:
524  result = 100276;
525  // bug 510: conjunctive tests' order needs to be ignored
526  //for (c=ct->data.disjunction_list; c!=NIL; c=c->rest)
527  // result = result + hash_test (thisAgent, static_cast<char *>(c->first));
528  return result;
529  case NOT_EQUAL_TEST:
530  case LESS_TEST:
531  case GREATER_TEST:
532  case LESS_OR_EQUAL_TEST:
534  case SAME_TYPE_TEST:
535  return (ct->type << 24) + ct->data.referent->common.hash_id;
536  default:
537  { char msg[BUFFER_MSG_SIZE];
538  strncpy (msg, "production.c: Error: bad test type in hash_test\n", BUFFER_MSG_SIZE);
539  msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
540  abort_with_fatal_error(thisAgent, msg);
541  }
542  }
543  return 0; /* unreachable, but without it, gcc -Wall warns here */
544 }
545 
546 /****************************/
547  /* ----------------------------------------------------------------
548  This returns a boolean that indicates that one condition is
549  greater than another in some ordering of the conditions. The ordering
550  is dependent upon the hash-value of each of the tests in the
551  condition.
552 ------------------------------------------------------------------*/
553 
554 #define NON_EQUAL_TEST_RETURN_VAL 0 /* some unusual number */
555 
557 {
558  Symbol *sym;
559 
560  if (test_is_blank_test(t))
562 
564  {
565  sym = referent_of_equality_test(t);
566  if (sym->common.symbol_type == SYM_CONSTANT_SYMBOL_TYPE ||
567  sym->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE ||
568  sym->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE)
569  {
570  return sym->common.hash_id;
571  }
572  else
574  }
576 }
577 
578 #define CANONICAL_TEST_ORDER canonical_test
579 
580 /*
581 #define CANONICAL_TEST_ORDER hash_test
582 */
583 
585 /*
586 
587  Original: 676,362 total rete nodes (1 dummy + 560045 positive + 4
588  unhashed positive + 2374 negative + 113938 p_nodes)
589 
590 The following notation describes the order of tests and the relation
591 of the hash_test that was used. IAV< means test the (I)d field first
592 then the (A)ttribute field, then the (V)alue field. and use less than
593 as the ordering constraint. The actual ordering constraint should not
594 make any difference.
595 
596  IAV<: 737,605 total rete nodes (1 dummy + 617394 positive + 3
597  unhashed positive + 6269 negative + 113938 p_nodes)
598 
599 Realized that the identifier will always be a variable and thus
600 shouldn't be part of the ordering.
601 
602 Changed to put all negative tests in front of cost 1 tests list.
603  That is always break ties of cost 1 with a negative test if
604  it exists.
605 
606 Changed so that canonical_test_order returns a negative -1 when
607 comparing anything but constants. Also fixed a bug.
608 
609 Consistency checks:
610 
611  Original: 676,362 total rete nodes (1 dummy + 560045 positive + 4
612  unhashed positive + 2374 negative + 113938 p_nodes)
613  Still holds with 1 optimization in and always returning False
614 
615  Remove 1: 720,126 total rete nodes (1 dummy + 605760 positive + 4
616  unhashed positive + 423 negative + 113938 p_nodes)
617  Always returning False causes the first item in the tie list to
618  be picked.
619 
620  Surprise: 637,482 total rete nodes (1 dummy + 523251 positive + 3
621  unhashed positive + 289 negative + 113938 p_nodes)
622  Without 1 optimization and always returning True. Causes the
623  last item in 1-tie list to be picked.
624 
625  In the following tests ht means hash test provided the canonical
626  value. ct means that the routine constant test provided the canonical
627  value. ct provides a value for non constant equality tests. I tried
628  both 0 and a big number (B) with no difference noted.
629 
630  ht_AV<: 714,427 total rete nodes (1 dummy + 600197 positive + 2
631  unhashed positive + 289 negative + 113938 p_nodes)
632 
633  ht_AV>: 709,637 total rete nodes (1 dummy + 595305 positive + 3
634  unhashed positive + 390 negative + 113938 p_nodes)
635 
636  ct0_AV>: 709,960 total rete nodes (1 dummy + 595628 positive + 3
637  unhashed positive + 390 negative + 113938 p_nodes)
638 
639  ct0_AV<: 714,162 total rete nodes (1 dummy + 599932 positive + 2
640  unhashed positive + 289 negative + 113938 p_nodes)
641 
642  ctB_AV>: 709,960 total rete nodes (1 dummy + 595628 positive + 3
643  unhashed positive + 390 negative + 113938 p_nodes)
644 
645  ctB_AV<: 714,162 total rete nodes (1 dummy + 599932 positive + 2
646  unhashed positive + 289 negative + 113938 p_nodes)
647 
648  ctB_VA>: 691,193 total rete nodes (1 dummy + 576861 positive + 3
649  unhashed positive + 390 negative + 113938 p_nodes)
650 
651  ctB_VA<: 704,539 total rete nodes (1 dummy + 590309 positive + 2
652  unhashed positive + 289 negative + 113938 p_nodes)
653 
654  ct0_VA<: 744,604 total rete nodes (1 dummy + 630374 positive + 2
655  unhashed positive + 289 negative + 113938 p_nodes)
656 
657  ct0_VA>: 672,367 total rete nodes (1 dummy + 558035 positive + 3
658  unhashed positive + 390 negative + 113938 p_nodes)
659 
660  ht_VA>: 727,742 total rete nodes (1 dummy + 613517 positive + 3
661  unhashed positive + 283 negative + 113938 p_nodes)
662 
663  ht_VA<: 582,559 total rete nodes (1 dummy + 468328 positive + 3
664  unhashed positive + 289 negative + 113938 p_nodes)
665 
666 Changed < to > 10/5/92*/
667 {
668  uint32_t test_order_1,test_order_2;
669 
670  if ((test_order_1 = CANONICAL_TEST_ORDER(c1->data.tests.attr_test)) <
671  (test_order_2 = CANONICAL_TEST_ORDER(c2->data.tests.attr_test))) {
672  return TRUE;
673  } else if (test_order_1 == test_order_2 &&
676  return TRUE;
677  }
678  return FALSE;
679 }
680 
681 /* ----------------------------------------------------------------
682  Returns TRUE iff the test contains an equality test for the given
683  symbol. If sym==NIL, returns TRUE iff the test contains any
684  equality test.
685 ---------------------------------------------------------------- */
686 
688  cons *c;
689  complex_test *ct;
690 
691  if (test_is_blank_test(t)) return FALSE;
692 
694  if (sym) return (referent_of_equality_test(t) == sym);
695  return TRUE;
696  }
697 
698  ct = complex_test_from_test(t);
699 
700  if (ct->type==CONJUNCTIVE_TEST) {
701  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
702  if (test_includes_equality_test_for_symbol (static_cast<char *>(c->first), sym)) return TRUE;
703  }
704  return FALSE;
705 }
706 
707 /* ----------------------------------------------------------------
708  Looks for goal or impasse tests (as directed by the two flag
709  parameters) in the given test, and returns TRUE if one is found.
710 ---------------------------------------------------------------- */
711 
713  Bool look_for_goal,
714  Bool look_for_impasse) {
715  complex_test *ct;
716  cons *c;
717 
718  if (test_is_blank_or_equality_test(t)) return FALSE;
719  ct = complex_test_from_test(t);
720  if (look_for_goal && (ct->type==GOAL_ID_TEST)) return TRUE;
721  if (look_for_impasse && (ct->type==IMPASSE_ID_TEST)) return TRUE;
722  if (ct->type == CONJUNCTIVE_TEST) {
723  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
724  if (test_includes_goal_or_impasse_id_test (static_cast<char *>(c->first),
725  look_for_goal,
726  look_for_impasse))
727  return TRUE;
728  return FALSE;
729  }
730  return FALSE;
731 }
732 
733 /* ----------------------------------------------------------------
734  Looks through a test, and returns a new copy of the first equality
735  test it finds. Signals an error if there is no equality test in
736  the given test.
737 ---------------------------------------------------------------- */
738 
740  complex_test *ct;
741  cons *c;
742  char msg[BUFFER_MSG_SIZE];
743 
744  if (test_is_blank_test(t)) {
745  strncpy (msg, "Internal error: can't find equality test in test\n", BUFFER_MSG_SIZE);
746  msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
747  abort_with_fatal_error(thisAgent, msg);
748  }
749  if (test_is_blank_or_equality_test(t)) return copy_test (thisAgent, t);
750  ct = complex_test_from_test(t);
751  if (ct->type==CONJUNCTIVE_TEST) {
752  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
753  if ( (! test_is_blank_test (static_cast<test>(c->first))) &&
754  (test_is_blank_or_equality_test (static_cast<test>(c->first))) )
755  return copy_test (thisAgent, static_cast<char *>(c->first));
756  }
757  strncpy (msg, "Internal error: can't find equality test in test\n",BUFFER_MSG_SIZE);
758  abort_with_fatal_error(thisAgent, msg);
759  return 0; /* unreachable, but without it, gcc -Wall warns here */
760 }
761 
762 /* =================================================================
763 
764  Utility Routines for Conditions
765 
766 ================================================================= */
767 
768 /* ----------------------------------------------------------------
769  Deallocates a condition list (including any NCC's and tests in it).
770 ---------------------------------------------------------------- */
771 
773  condition *cond_list) {
774  condition *c;
775 
776  while (cond_list) {
777  c = cond_list;
778  cond_list = cond_list->next;
780  deallocate_condition_list (thisAgent, c->data.ncc.top);
781  } else { /* positive and negative conditions */
782  quickly_deallocate_test (thisAgent, c->data.tests.id_test);
785  }
786  free_with_pool (&thisAgent->condition_pool, c);
787  }
788 }
789 
790 /* ----------------------------------------------------------------
791  Returns a new copy of the given condition.
792 ---------------------------------------------------------------- */
793 
795  condition *cond) {
796  condition *New;
797 
798  if (!cond) return NIL;
799  allocate_with_pool (thisAgent, &thisAgent->condition_pool, &New);
800  New->type = cond->type;
801 
802  switch (cond->type) {
803  case POSITIVE_CONDITION:
804  New->bt = cond->bt;
805  /* ... and fall through to next case */
806  case NEGATIVE_CONDITION:
807  New->data.tests.id_test = copy_test (thisAgent, cond->data.tests.id_test);
808  New->data.tests.attr_test = copy_test (thisAgent, cond->data.tests.attr_test);
809  New->data.tests.value_test = copy_test (thisAgent, cond->data.tests.value_test);
811  break;
813  copy_condition_list (thisAgent, cond->data.ncc.top, &(New->data.ncc.top),
814  &(New->data.ncc.bottom));
815  break;
816  }
817  return New;
818 }
819 
820 /* ----------------------------------------------------------------
821  Copies the given condition list, returning pointers to the
822  top-most and bottom-most conditions in the new copy.
823 ---------------------------------------------------------------- */
824 
825 void copy_condition_list (agent* thisAgent,
826  condition *top_cond,
827  condition **dest_top,
828  condition **dest_bottom) {
829  condition *New, *prev;
830 
831  prev = NIL;
832  while (top_cond) {
833  New = copy_condition (thisAgent, top_cond);
834  if (prev) prev->next = New; else *dest_top = New;
835  New->prev = prev;
836  prev = New;
837  top_cond = top_cond->next;
838  }
839  if (prev) prev->next = NIL; else *dest_top = NIL;
840  *dest_bottom = prev;
841 }
842 
843 /* ----------------------------------------------------------------
844  Returns TRUE iff the two conditions are identical.
845 ---------------------------------------------------------------- */
846 
848  if (c1->type != c2->type) return FALSE;
849  bool neg = true;
850  switch (c1->type) {
851  case POSITIVE_CONDITION:
852  neg = false;
853  case NEGATIVE_CONDITION:
854  if (! tests_are_equal (c1->data.tests.id_test,
855  c2->data.tests.id_test, neg))
856  return FALSE;
857  if (! tests_are_equal (c1->data.tests.attr_test,
858  c2->data.tests.attr_test, neg))
859  return FALSE;
861  c2->data.tests.value_test, neg))
862  return FALSE;
865  return FALSE;
866  return TRUE;
867 
869  for (c1=c1->data.ncc.top, c2=c2->data.ncc.top;
870  ((c1!=NIL)&&(c2!=NIL));
871  c1=c1->next, c2=c2->next)
872  if (! conditions_are_equal (c1,c2)) return FALSE;
873  if (c1==c2) return TRUE; /* make sure they both hit end-of-list */
874  return FALSE;
875  }
876  return FALSE; /* unreachable, but without it, gcc -Wall warns here */
877 }
878 
879 /* ----------------------------------------------------------------
880  Returns a hash value for the given condition.
881 ---------------------------------------------------------------- */
882 
884  condition *cond) {
885  uint32_t result;
886  condition *c;
887 
888  switch (cond->type) {
889  case POSITIVE_CONDITION:
890  result = hash_test (thisAgent, cond->data.tests.id_test);
891  result = (result << 24) | (result >> 8);
892  result ^= hash_test (thisAgent, cond->data.tests.attr_test);
893  result = (result << 24) | (result >> 8);
894  result ^= hash_test (thisAgent, cond->data.tests.value_test);
895  if (cond->test_for_acceptable_preference) result++;
896  break;
897  case NEGATIVE_CONDITION:
898  result = 1267818;
899  result ^= hash_test (thisAgent, cond->data.tests.id_test);
900  result = (result << 24) | (result >> 8);
901  result ^= hash_test (thisAgent, cond->data.tests.attr_test);
902  result = (result << 24) | (result >> 8);
903  result ^= hash_test (thisAgent, cond->data.tests.value_test);
904  if (cond->test_for_acceptable_preference) result++;
905  break;
907  result = 82348149;
908  for (c=cond->data.ncc.top; c!=NIL; c=c->next) {
909  result ^= hash_condition (thisAgent, c);
910  result = (result << 24) | (result >> 8);
911  }
912  break;
913  default:
914  { char msg[BUFFER_MSG_SIZE];
915  strncpy (msg, "Internal error: bad cond type in hash_condition\n", BUFFER_MSG_SIZE);
916  msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
917  abort_with_fatal_error(thisAgent, msg);
918  }
919  result = 0; /* unreachable, but gcc -Wall warns without it */
920  }
921  return result;
922 }
923 
924 /* =================================================================
925 
926  Utility Routines for Actions and RHS Values
927 
928 ================================================================= */
929 
930 /* ----------------------------------------------------------------
931  Deallocates the given rhs_value.
932 ---------------------------------------------------------------- */
933 
934 void deallocate_rhs_value (agent* thisAgent, rhs_value rv) {
935  cons *c;
936  list *fl;
937 
938  if (rhs_value_is_reteloc(rv)) return;
939  if (rhs_value_is_unboundvar(rv)) return;
940  if (rhs_value_is_funcall(rv)) {
941  fl = rhs_value_to_funcall_list(rv);
942  for (c=fl->rest; c!=NIL; c=c->rest)
943  deallocate_rhs_value (thisAgent, static_cast<char *>(c->first));
944  free_list (thisAgent, fl);
945  } else {
946  symbol_remove_ref (thisAgent, rhs_value_to_symbol(rv));
947  }
948 }
949 
950 /* ----------------------------------------------------------------
951  Returns a new copy of the given rhs_value.
952 ---------------------------------------------------------------- */
953 
955  cons *c, *new_c, *prev_new_c;
956  list *fl, *new_fl;
957 
958  if (rhs_value_is_reteloc(rv)) return rv;
959  if (rhs_value_is_unboundvar(rv)) return rv;
960  if (rhs_value_is_funcall(rv)) {
961  fl = rhs_value_to_funcall_list(rv);
962  allocate_cons (thisAgent, &new_fl);
963  new_fl->first = fl->first;
964  prev_new_c = new_fl;
965  for (c=fl->rest; c!=NIL; c=c->rest) {
966  allocate_cons (thisAgent, &new_c);
967  new_c->first = copy_rhs_value (thisAgent, static_cast<char *>(c->first));
968  prev_new_c->rest = new_c;
969  prev_new_c = new_c;
970  }
971  prev_new_c->rest = NIL;
972  return funcall_list_to_rhs_value (new_fl);
973  } else {
975  return rv;
976  }
977 }
978 
979 /* ----------------------------------------------------------------
980  Deallocates the given action (singly-linked) list.
981 ---------------------------------------------------------------- */
982 
983 void deallocate_action_list (agent* thisAgent, action *actions) {
984  action *a;
985 
986  while (actions) {
987  a = actions;
988  actions = actions->next;
989  if (a->type==FUNCALL_ACTION) {
990  deallocate_rhs_value (thisAgent, a->value);
991  } else {
992  /* --- make actions --- */
993  deallocate_rhs_value (thisAgent, a->id);
994  deallocate_rhs_value (thisAgent, a->attr);
995  deallocate_rhs_value (thisAgent, a->value);
997  deallocate_rhs_value (thisAgent, a->referent);
998  }
999  free_with_pool (&thisAgent->action_pool,a);
1000  }
1001 }
1002 
1003 /* -----------------------------------------------------------------
1004  Find first letter of rhs_value, or '*' if nothing appropriate.
1005  (See comments on first_letter_from_symbol for more explanation.)
1006 ----------------------------------------------------------------- */
1007 
1009  if (rhs_value_is_symbol(rv))
1011  return '*'; /* function calls, reteloc's, unbound variables */
1012 }
1013 
1014 /* =================================================================
1015 
1016  Utility Routines for Nots
1017 
1018 ================================================================= */
1019 
1020 /* ----------------------------------------------------------------
1021  Deallocates the given (singly-linked) list of Nots.
1022 ---------------------------------------------------------------- */
1023 
1024 void deallocate_list_of_nots (agent* thisAgent,
1025  not_struct *nots) {
1026  not_struct *temp;
1027 
1028  while (nots) {
1029  temp = nots;
1030  nots = nots->next;
1031  symbol_remove_ref (thisAgent, temp->s1);
1032  symbol_remove_ref (thisAgent, temp->s2);
1033  free_with_pool (&thisAgent->not_pool, temp);
1034  }
1035 }
1036 
1037 /* *********************************************************************
1038 
1039  Transitive Closure Utilities
1040 
1041 ********************************************************************* */
1042 
1043 /* =====================================================================
1044 
1045  Increment TC Counter and Return New TC Number
1046 
1047  Get_new_tc_number() is called from lots of places. Any time we need
1048  to mark a set of identifiers and/or variables, we get a new tc_number
1049  by calling this routine, then proceed to mark various ids or vars
1050  by setting the sym->id.tc_num or sym->var.tc_num fields.
1051 
1052  A global tc number counter is maintained and incremented by this
1053  routine in order to generate a different tc_number each time. If
1054  the counter ever wraps around back to 0, we bump it up to 1 and
1055  reset the the tc_num fields on all existing identifiers and variables
1056  to 0.
1057 ===================================================================== */
1058 
1060  /* This was originally a global variable. For the present I'll move it here,
1061  but it probably belongs in kernel_struct. */
1062 
1063  thisAgent->current_tc_number++;
1064  if (thisAgent->current_tc_number==0) {
1066  thisAgent->current_tc_number = 1;
1067  }
1068  return thisAgent->current_tc_number;
1069 }
1070 
1071 /* =====================================================================
1072 
1073  Marking, Unmarking, and Collecting Symbols
1074 
1075  Sometimes in addition to marking symbols using their tc_num fields,
1076  we also want to build up a list of the symbols we've marked. So,
1077  many routines in this file take an "id_list" or "var_list" argument.
1078  This argument should be NIL if no such list is desired. If non-NIL,
1079  it should point to the header of the linked list being built.
1080 
1081  Mark_identifier_if_unmarked() and mark_variable_if_unmarked() are
1082  macros for adding id's and var's to the set of symbols.
1083 
1084  Unmark_identifiers_and_free_list() unmarks all the id's in the given
1085  list, and deallocates the list. Unmark_variables_and_free_list()
1086  is similar, only the list should be a list of variables rather than
1087  identifiers.
1088 
1089  Symbol_is_constant_or_marked_variable() tests whether the given symbol
1090  is either a constant (non-variable) or a variable marked with the
1091  given tc number.
1092 ===================================================================== */
1093 
1094 /*#define mark_identifier_if_unmarked(ident,tc,id_list) { \
1095  if ((ident)->id.tc_num != (tc)) { \
1096  (ident)->id.tc_num = (tc); \
1097  if (id_list) push ((ident),(*(id_list))); } }*/
1098 inline void mark_identifier_if_unmarked(agent* thisAgent,
1099  Symbol * ident, tc_number tc, list ** id_list)
1100 {
1101  if ((ident)->id.tc_num != (tc))
1102  {
1103  (ident)->id.tc_num = (tc);
1104  if (id_list)
1105  push (thisAgent, (ident),(*(id_list)));
1106  }
1107 }
1108 
1109 /*#define mark_variable_if_unmarked(v,tc,var_list) { \
1110  if ((v)->var.tc_num != (tc)) { \
1111  (v)->var.tc_num = (tc); \
1112  if (var_list) push ((v),(*(var_list))); } }*/
1113 inline void mark_variable_if_unmarked(agent* thisAgent, Symbol * v,
1114  tc_number tc, list ** var_list)
1115 {
1116  if ((v)->var.tc_num != (tc))
1117  {
1118  (v)->var.tc_num = (tc);
1119  if (var_list) push (thisAgent, (v),(*(var_list)));
1120  }
1121 }
1122 
1123 void unmark_identifiers_and_free_list (agent* thisAgent, list *id_list) {
1124  cons *next;
1125  Symbol *sym;
1126 
1127  while (id_list) {
1128  sym = static_cast<symbol_union *>(id_list->first);
1129  next = id_list->rest;
1130  free_cons (thisAgent, id_list);
1131  sym->id.tc_num = 0;
1132  id_list = next;
1133  }
1134 }
1135 
1136 void unmark_variables_and_free_list (agent* thisAgent, list *var_list) {
1137  cons *next;
1138  Symbol *sym;
1139 
1140  while (var_list) {
1141  sym = static_cast<symbol_union *>(var_list->first);
1142  next = var_list->rest;
1143  free_cons (thisAgent, var_list);
1144  sym->var.tc_num = 0;
1145  var_list = next;
1146  }
1147 }
1148 
1149 /* =====================================================================
1150 
1151  Finding the variables bound in tests, conditions, and condition lists
1152 
1153  These routines collect the variables that are bound in tests, etc. Their
1154  "var_list" arguments should either be NIL or else should point to
1155  the header of the list of marked variables being constructed.
1156 ===================================================================== */
1157 
1159  tc_number tc, list **var_list) {
1160  cons *c;
1161  Symbol *referent;
1162  complex_test *ct;
1163 
1164  if (test_is_blank_test(t)) return;
1165 
1167  referent = referent_of_equality_test(t);
1168  if (referent->common.symbol_type==VARIABLE_SYMBOL_TYPE)
1169  mark_variable_if_unmarked (thisAgent, referent, tc, var_list);
1170  return;
1171  }
1172 
1173  ct = complex_test_from_test(t);
1174  if (ct->type==CONJUNCTIVE_TEST) {
1175  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
1176  add_bound_variables_in_test (thisAgent, static_cast<char *>(c->first), tc, var_list);
1177  }
1178 }
1179 
1181  list **var_list) {
1182  if (c->type!=POSITIVE_CONDITION) return;
1183  add_bound_variables_in_test (thisAgent, c->data.tests.id_test, tc, var_list);
1184  add_bound_variables_in_test (thisAgent, c->data.tests.attr_test, tc, var_list);
1185  add_bound_variables_in_test (thisAgent, c->data.tests.value_test, tc, var_list);
1186 }
1187 
1189  tc_number tc, list **var_list) {
1190  condition *c;
1191 
1192  for (c=cond_list; c!=NIL; c=c->next)
1193  add_bound_variables_in_condition (thisAgent, c, tc, var_list);
1194 }
1195 
1196 /* =====================================================================
1197 
1198  Finding all variables from tests, conditions, and condition lists
1199 
1200  These routines collect all the variables in tests, etc. Their
1201  "var_list" arguments should either be NIL or else should point to
1202  the header of the list of marked variables being constructed.
1203 ===================================================================== */
1204 
1205 void add_all_variables_in_test (agent* thisAgent, test t,
1206  tc_number tc, list **var_list) {
1207  cons *c;
1208  Symbol *referent;
1209  complex_test *ct;
1210 
1211  if (test_is_blank_test(t)) return;
1212 
1214  referent = referent_of_equality_test(t);
1215  if (referent->common.symbol_type==VARIABLE_SYMBOL_TYPE)
1216  mark_variable_if_unmarked (thisAgent, referent, tc, var_list);
1217  return;
1218  }
1219 
1220  ct = complex_test_from_test(t);
1221 
1222  switch (ct->type) {
1223  case GOAL_ID_TEST:
1224  case IMPASSE_ID_TEST:
1225  case DISJUNCTION_TEST:
1226  break;
1227 
1228  case CONJUNCTIVE_TEST:
1229  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
1230  add_all_variables_in_test (thisAgent, static_cast<char *>(c->first), tc, var_list);
1231  break;
1232 
1233  default:
1234  /* --- relational tests other than equality --- */
1235  referent = ct->data.referent;
1236  if (referent->common.symbol_type==VARIABLE_SYMBOL_TYPE)
1237  mark_variable_if_unmarked (thisAgent, referent, tc, var_list);
1238  break;
1239  }
1240 }
1241 
1242 void add_all_variables_in_condition_list (agent* thisAgent, condition *cond_list,
1243  tc_number tc, list **var_list);
1244 
1246  condition *c, tc_number tc,
1247  list **var_list) {
1249  add_all_variables_in_condition_list (thisAgent, c->data.ncc.top, tc, var_list);
1250  } else {
1251  add_all_variables_in_test (thisAgent, c->data.tests.id_test, tc, var_list);
1252  add_all_variables_in_test (thisAgent, c->data.tests.attr_test, tc, var_list);
1253  add_all_variables_in_test (thisAgent, c->data.tests.value_test, tc, var_list);
1254  }
1255 }
1256 
1258  tc_number tc, list **var_list) {
1259  condition *c;
1260 
1261  for (c=cond_list; c!=NIL; c=c->next)
1262  add_all_variables_in_condition (thisAgent, c, tc, var_list);
1263 }
1264 
1265 /* =====================================================================
1266 
1267  Finding all variables from rhs_value's, actions, and action lists
1268 
1269  These routines collect all the variables in rhs_value's, etc. Their
1270  "var_list" arguments should either be NIL or else should point to
1271  the header of the list of marked variables being constructed.
1272 
1273  Warning: These are part of the reorderer and handle only productions
1274  in non-reteloc, etc. format. They don't handle reteloc's or
1275  RHS unbound variables.
1276 ===================================================================== */
1277 
1279  rhs_value rv, tc_number tc,
1280  list **var_list) {
1281  list *fl;
1282  cons *c;
1283  Symbol *sym;
1284 
1285  if (rhs_value_is_symbol(rv)) {
1286  /* --- ordinary values (i.e., symbols) --- */
1287  sym = rhs_value_to_symbol(rv);
1288  if (sym->common.symbol_type==VARIABLE_SYMBOL_TYPE)
1289  mark_variable_if_unmarked (thisAgent, sym, tc, var_list);
1290  } else {
1291  /* --- function calls --- */
1292  fl = rhs_value_to_funcall_list(rv);
1293  for (c=fl->rest; c!=NIL; c=c->rest)
1294  add_all_variables_in_rhs_value (thisAgent, static_cast<char *>(c->first), tc, var_list);
1295  }
1296 }
1297 
1299  tc_number tc, list **var_list){
1300  Symbol *id;
1301 
1302  if (a->type==MAKE_ACTION) {
1303  /* --- ordinary make actions --- */
1304  id = rhs_value_to_symbol(a->id);
1305  if (id->common.symbol_type==VARIABLE_SYMBOL_TYPE)
1306  mark_variable_if_unmarked (thisAgent, id, tc, var_list);
1307  add_all_variables_in_rhs_value (thisAgent, a->attr, tc, var_list);
1308  add_all_variables_in_rhs_value (thisAgent, a->value, tc, var_list);
1310  add_all_variables_in_rhs_value (thisAgent, a->referent, tc, var_list);
1311  } else {
1312  /* --- function call actions --- */
1313  add_all_variables_in_rhs_value (thisAgent, a->value, tc, var_list);
1314  }
1315 }
1316 
1318  list **var_list) {
1319  action *a;
1320 
1321  for (a=actions; a!=NIL; a=a->next)
1322  add_all_variables_in_action (thisAgent, a, tc, var_list);
1323 }
1324 
1325 /* ====================================================================
1326 
1327  Transitive Closure for Conditions and Actions
1328 
1329  These routines do transitive closure calculations for tests,
1330  conditions, actions, etc.
1331 
1332  Usage:
1333  1. Set my_tc = get_new_tc_number() to start a new TC
1334  2. (optional) If you want linked lists of symbols in the TC, initialize
1335  id_list=NIL and var_list=NIL.
1336  If you're not using id_list and/or var_list, give NIL for "&id_list"
1337  and/or "&var_list" in the function calls below.
1338  3. (optional) setup any id's or var's that you want to include in the
1339  initial TC, by calling
1340  add_symbol_to_tc (sym, my_tc, &id_list, &var_list)
1341  (If not using id_list or var_list, you can just mark
1342  sym->{id,var}.tc_num = my_tc instead.)
1343  4. To do the work you want, use any of the following any number of times:
1344  add_cond_to_tc (cond, my_tc, &id_list, &var_list);
1345  add_action_to_tc (cond, my_tc, &id_list, &var_list);
1346  result = cond_is_in_tc (cond, my_tc);
1347  result = action_is_in_tc (action, my_tc);
1348  5. When finished, free the cons cells in id_list and var_list (but
1349  don't call symbol_remove_ref() on the symbols in them).
1350 
1351  Warning: actions must not contain reteloc's or rhs unbound variables here.
1352 ==================================================================== */
1353 
1354 void add_symbol_to_tc (agent* thisAgent, Symbol *sym, tc_number tc,
1355  list **id_list, list **var_list) {
1356  if (sym->common.symbol_type==VARIABLE_SYMBOL_TYPE) {
1357  mark_variable_if_unmarked (thisAgent, sym, tc, var_list);
1358  } else if (sym->common.symbol_type==IDENTIFIER_SYMBOL_TYPE) {
1359  mark_identifier_if_unmarked (thisAgent, sym, tc, id_list);
1360  }
1361 }
1362 
1363 void add_test_to_tc (agent* thisAgent, test t, tc_number tc,
1364  list **id_list, list **var_list) {
1365  cons *c;
1366  complex_test *ct;
1367 
1368  if (test_is_blank_test(t)) return;
1369 
1371  add_symbol_to_tc (thisAgent, referent_of_equality_test(t), tc, id_list, var_list);
1372  return;
1373  }
1374 
1375  ct = complex_test_from_test(t);
1376  if (ct->type == CONJUNCTIVE_TEST) {
1377  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
1378  add_test_to_tc (thisAgent, static_cast<char *>(c->first), tc, id_list, var_list);
1379  }
1380 }
1381 
1382 void add_cond_to_tc (agent* thisAgent, condition *c, tc_number tc,
1383  list **id_list, list **var_list) {
1384  if (c->type==POSITIVE_CONDITION) {
1385  add_test_to_tc (thisAgent, c->data.tests.id_test, tc, id_list, var_list);
1386  add_test_to_tc (thisAgent, c->data.tests.value_test, tc, id_list, var_list);
1387  }
1388 }
1389 
1390 void add_action_to_tc (agent* thisAgent, action *a, tc_number tc,
1391  list **id_list, list **var_list) {
1392  if (a->type != MAKE_ACTION) return;
1393  add_symbol_to_tc (thisAgent, rhs_value_to_symbol(a->id), tc, id_list, var_list);
1394  if (rhs_value_is_symbol(a->value))
1395  add_symbol_to_tc (thisAgent, rhs_value_to_symbol(a->value), tc, id_list, var_list);
1397  if (rhs_value_is_symbol(a->referent))
1398  add_symbol_to_tc (thisAgent, rhs_value_to_symbol(a->referent),tc,id_list,var_list);
1399 }
1400 
1402  if (sym->common.symbol_type==VARIABLE_SYMBOL_TYPE)
1403  return (sym->var.tc_num == tc);
1404  if (sym->common.symbol_type==IDENTIFIER_SYMBOL_TYPE)
1405  return (sym->id.tc_num == tc);
1406  return FALSE;
1407 }
1408 
1410  cons *c;
1411  complex_test *ct;
1412 
1413  if (test_is_blank_test(t)) return FALSE;
1416  }
1417 
1418  ct = complex_test_from_test(t);
1419  if (ct->type==CONJUNCTIVE_TEST) {
1420  for (c=ct->data.conjunct_list; c!=NIL; c=c->rest)
1421  if (test_is_in_tc (static_cast<char *>(c->first), tc)) return TRUE;
1422  return FALSE;
1423  }
1424  return FALSE;
1425 }
1426 
1427 Bool cond_is_in_tc (agent* thisAgent, condition *cond, tc_number tc) {
1428  condition *c;
1429  Bool anything_changed;
1430  Bool result;
1431  list *new_ids, *new_vars;
1432 
1433  if (cond->type != CONJUNCTIVE_NEGATION_CONDITION)
1434  return test_is_in_tc (cond->data.tests.id_test, tc);
1435 
1436  /* --- conjunctive negations: keep trying to add stuff to the TC --- */
1437  new_ids = NIL;
1438  new_vars = NIL;
1439  for (c=cond->data.ncc.top; c!=NIL; c=c->next)
1440  c->already_in_tc = FALSE;
1441  while (TRUE) {
1442  anything_changed = FALSE;
1443  for (c=cond->data.ncc.top; c!=NIL; c=c->next)
1444  if (! c->already_in_tc)
1445  if (cond_is_in_tc (thisAgent, c, tc)) {
1446  add_cond_to_tc (thisAgent, c, tc, &new_ids, &new_vars);
1447  c->already_in_tc = TRUE;
1448  anything_changed = TRUE;
1449  }
1450  if (! anything_changed) break;
1451  }
1452 
1453  /* --- complete TC found, look for anything that didn't get hit --- */
1454  result = TRUE;
1455  for (c=cond->data.ncc.top; c!=NIL; c=c->next)
1456  if (! c->already_in_tc) result = FALSE;
1457 
1458  /* --- unmark identifiers and variables that we just marked --- */
1459  unmark_identifiers_and_free_list (thisAgent, new_ids);
1460  unmark_variables_and_free_list (thisAgent, new_vars);
1461 
1462  return result;
1463 }
1464 
1466  if (a->type != MAKE_ACTION) return FALSE;
1467  return symbol_is_in_tc (rhs_value_to_symbol(a->id), tc);
1468 }
1469 
1470 /* *********************************************************************
1471 
1472  Variable Generator
1473 
1474  These routines are used for generating new variables. The variables
1475  aren't necessarily "completely" new--they might occur in some existing
1476  production. But we usually need to make sure the new variables don't
1477  overlap with those already used in a *certain* production--for instance,
1478  when variablizing a chunk, we don't want to introduce a new variable that
1479  conincides with the name of a variable already in an NCC in the chunk.
1480 
1481  To use these routines, first call reset_variable_generator(), giving
1482  it lists of conditions and actions whose variables should not be
1483  used. Then call generate_new_variable() any number of times; each
1484  time, you give it a string to use as the prefix for the new variable's
1485  name. The prefix string should not include the opening "<".
1486 ********************************************************************* */
1487 
1488 
1490  condition *conds_with_vars_to_avoid,
1491  action *actions_with_vars_to_avoid) {
1492  tc_number tc;
1493  list *var_list;
1494  cons *c;
1495  int i;
1496 
1497  /* --- reset counts, and increment the gensym number --- */
1498  for (i=0; i<26; i++) thisAgent->gensymed_variable_count[i] = 1;
1499  thisAgent->current_variable_gensym_number++;
1500  if (thisAgent->current_variable_gensym_number==0) {
1501  reset_variable_gensym_numbers (thisAgent);
1502  thisAgent->current_variable_gensym_number = 1;
1503  }
1504 
1505  /* --- mark all variables in the given conds and actions --- */
1506  tc = get_new_tc_number(thisAgent);
1507  var_list = NIL;
1508  add_all_variables_in_condition_list (thisAgent, conds_with_vars_to_avoid,tc, &var_list);
1509  add_all_variables_in_action_list (thisAgent, actions_with_vars_to_avoid, tc, &var_list);
1510  for (c=var_list; c!=NIL; c=c->rest)
1511  static_cast<Symbol *>(c->first)->var.gensym_number = thisAgent->current_variable_gensym_number;
1512  free_list (thisAgent, var_list);
1513 }
1514 
1515 Symbol *generate_new_variable (agent* thisAgent, const char *prefix) {
1516 #define GENERATE_NEW_VARIABLE_BUFFER_SIZE 200 /* that ought to be long enough! */
1518  Symbol *New;
1519  char first_letter;
1520 
1521  first_letter = *prefix;
1522  if (isalpha(first_letter)) {
1523  if (isupper(first_letter)) first_letter = static_cast<char>(tolower(first_letter));
1524  } else {
1525  first_letter = 'v';
1526  }
1527 
1528  while (TRUE) {
1529  SNPRINTF (name,GENERATE_NEW_VARIABLE_BUFFER_SIZE, "<%s%lu>", prefix,
1530  static_cast<long unsigned int>(thisAgent->gensymed_variable_count[first_letter-'a']++));
1531  name[GENERATE_NEW_VARIABLE_BUFFER_SIZE - 1] = 0; /* ensure null termination */
1532 
1533  New = make_variable (thisAgent, name);
1534  if (New->var.gensym_number != thisAgent->current_variable_gensym_number) break;
1535  symbol_remove_ref (thisAgent, New);
1536  }
1537 
1538  New->var.current_binding_value = NIL;
1540  return New;
1541 }
1542 
1543 /* *********************************************************************
1544 
1545  Production Management
1546 
1547  Make_production() does reordering, compile-time o-support calc's,
1548  and builds and returns a production structure for a new production.
1549  It does not enter the production into the Rete net, however.
1550  The "type" argument should be one of USER_PRODUCTION_TYPE, etc.
1551  The flag "reorder_nccs" tells whether to recursively reorder
1552  the subconditions of NCC's--this is not necessary for newly
1553  built chunks, as their NCC's are copies of other NCC's in SP's that
1554  have already been reordered. If any error occurs, make_production()
1555  returns NIL.
1556 
1557  Deallocate_production() and excise_production() do just what they
1558  say. Normally deallocate_production() should be invoked only via
1559  the production_remove_ref() macro.
1560 ********************************************************************* */
1561 
1563  byte type,
1564  Symbol *name,
1565  condition **lhs_top,
1566  condition **lhs_bottom,
1567  action **rhs_top,
1568  Bool reorder_nccs) {
1569  production *p;
1570  tc_number tc;
1571  action *a;
1572 
1573 
1574  thisAgent->name_of_production_being_reordered = name->sc.name;
1575 
1576  if (type!=JUSTIFICATION_PRODUCTION_TYPE) {
1577  reset_variable_generator (thisAgent, *lhs_top, *rhs_top);
1578  tc = get_new_tc_number(thisAgent);
1579  add_bound_variables_in_condition_list (thisAgent, *lhs_top, tc, NIL);
1580  if (! reorder_action_list (thisAgent, rhs_top, tc)) return NIL;
1581  if (! reorder_lhs (thisAgent, lhs_top, lhs_bottom, reorder_nccs)) return NIL;
1582 
1583  if ( !smem_valid_production( *lhs_top, *rhs_top ) )
1584  {
1585  print( thisAgent, "ungrounded LTI in production\n" );
1586  return NIL;
1587  }
1588 
1589 #ifdef DO_COMPILE_TIME_O_SUPPORT_CALCS
1590  calculate_compile_time_o_support (*lhs_top, *rhs_top);
1591 #ifdef LIST_COMPILE_TIME_O_SUPPORT_FAILURES
1592  for (a = *rhs_top; a!=NIL; a=a->next)
1593  if ((a->type==MAKE_ACTION) && (a->support==UNKNOWN_SUPPORT)) break;
1594  if (a) print_with_symbols (thisAgent, "\nCan't classify %y\n", name);
1595 #endif
1596 #else
1597  for (a = *rhs_top; a!=NIL; a=a->next) a->support = UNKNOWN_SUPPORT;
1598 #endif
1599  } else {
1600  /* --- for justifications --- */
1601  /* force run-time o-support (it'll only be done once) */
1602  for (a = *rhs_top; a!=NIL; a=a->next) a->support = UNKNOWN_SUPPORT;
1603  }
1604 
1605  allocate_with_pool (thisAgent, &thisAgent->production_pool, &p);
1606  p->name = name;
1607  if (name->sc.production) {
1608  print (thisAgent, "Internal error: make_production called with name %s\n",
1610  print (thisAgent, "for which a production already exists\n");
1611  }
1612  name->sc.production = p;
1613  p->documentation = NIL;
1614  p->filename = NIL;
1615  p->firing_count = 0;
1616  p->reference_count = 1;
1617  insert_at_head_of_dll (thisAgent->all_productions_of_type[type], p, next, prev);
1618  thisAgent->num_productions_of_type[type]++;
1619  p->type = type;
1621  p->trace_firings = FALSE;
1622  p->p_node = NIL; /* it's not in the Rete yet */
1623  p->action_list = *rhs_top;
1624  p->rhs_unbound_variables = NIL; /* the Rete fills this in */
1625  p->instantiations = NIL;
1626  p->interrupt = FALSE;
1627 
1628  // Soar-RL stuff
1629  p->rl_update_count = 0.0;
1630  p->rl_delta_bar_delta_beta = -3.0;
1631  p->rl_delta_bar_delta_h = 0.0;
1632  p->rl_rule = false;
1633  p->rl_update_count = 0;
1634  p->rl_ref_count = 0;
1635  p->rl_ecr = 0.0;
1636  p->rl_efr = 0.0;
1637  if ( ( type != JUSTIFICATION_PRODUCTION_TYPE ) && ( type != TEMPLATE_PRODUCTION_TYPE ) )
1638  {
1639  p->rl_rule = rl_valid_rule( p );
1640  if ( p->rl_rule )
1641  {
1643  }
1644  }
1645  p->rl_template_conds = NIL;
1647 
1648  rl_update_template_tracking( thisAgent, name->sc.name );
1649 
1650  return p;
1651 }
1652 
1653 void deallocate_production (agent* thisAgent, production *prod) {
1654  if (prod->instantiations) {
1655  char msg[BUFFER_MSG_SIZE];
1656  strncpy (msg, "Internal error: deallocating prod. that still has inst's\n", BUFFER_MSG_SIZE);
1657  msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
1658  abort_with_fatal_error(thisAgent, msg);
1659  }
1660  deallocate_action_list (thisAgent, prod->action_list);
1661  /* RBD 3/28/95 the following line used to use free_list(), leaked memory */
1663  symbol_remove_ref (thisAgent, prod->name);
1664  if (prod->documentation) free_memory_block_for_string (thisAgent, prod->documentation);
1665  /* next line, kjh CUSP(B11) */
1666  if (prod->filename) free_memory_block_for_string (thisAgent, prod->filename);
1667 
1670 
1671  free_with_pool (&thisAgent->production_pool, prod);
1672 }
1673 
1674 void excise_production (agent* thisAgent, production *prod, Bool print_sharp_sign) {
1675  if (prod->trace_firings) remove_pwatch (thisAgent, prod);
1676  remove_from_dll (thisAgent->all_productions_of_type[prod->type], prod, next, prev);
1677 
1678  // Remove reference from apoptosis object store
1679  if ( ( prod->type == CHUNK_PRODUCTION_TYPE ) && ( thisAgent->rl_params ) && ( thisAgent->rl_params->apoptosis->get_value() != rl_param_container::apoptosis_none ) )
1680  thisAgent->rl_prods->remove_object( prod );
1681 
1682  // Remove RL-related pointers to this production
1683  if ( prod->rl_rule )
1684  rl_remove_refs_for_prod( thisAgent, prod );
1685 
1686  thisAgent->num_productions_of_type[prod->type]--;
1687  if (print_sharp_sign) print (thisAgent, "#");
1688  if (prod->p_node) excise_production_from_rete (thisAgent, prod);
1689  prod->name->sc.production = NIL;
1690  production_remove_ref (thisAgent, prod);
1691 }
1692 
1694  byte type,
1695  Bool print_sharp_sign) {
1696 
1697  // Iterating through the productions of the appropriate type and excising them
1698  while (thisAgent->all_productions_of_type[type]) {
1699  excise_production (thisAgent,
1700  thisAgent->all_productions_of_type[type],
1701  print_sharp_sign&&thisAgent->sysparams[TRACE_LOADING_SYSPARAM]);
1702  }
1703 }
1704 
1706  Bool print_sharp_sign) {
1707 
1708  // Excise all the productions of the four different types
1709  for (int i=0; i < NUM_PRODUCTION_TYPES; i++) {
1710  excise_all_productions_of_type(thisAgent,
1711  static_cast<byte>(i),
1712  print_sharp_sign&&thisAgent->sysparams[TRACE_LOADING_SYSPARAM]);
1713  }
1714 }