1 ///////////////////////////////////////////////////////////////////////////////
2 // This file is generated automatically using Prop (version 2.3.6),
3 // last updated on Nov 2, 1999.
4 // The original source file is "infgen.pcc".
5 ///////////////////////////////////////////////////////////////////////////////
7 #define PROP_STRCMP_USED
10 ///////////////////////////////////////////////////////////////////////////////
12 // This file implements the inference rules compiler of Prop.
14 ///////////////////////////////////////////////////////////////////////////////
16 #include <AD/memory/mempool.h>
17 #include <AD/generic/ordering.h>
28 ///////////////////////////////////////////////////////////////////////////////
30 // Constructor and destructor for the inference compiler
32 ///////////////////////////////////////////////////////////////////////////////
33 InferenceCompiler:: InferenceCompiler() {}
34 InferenceCompiler::~InferenceCompiler() {}
36 ///////////////////////////////////////////////////////////////////////////////
38 // Import some type definitions.
40 ///////////////////////////////////////////////////////////////////////////////
41 typedef HashTable::Key Key
;
42 typedef HashTable::Value Value
;
44 ///////////////////////////////////////////////////////////////////////////////
46 // Method to create an inference class.
48 ///////////////////////////////////////////////////////////////////////////////
49 InferenceClass::InferenceClass(Id id
, Inherits i
, TyQual qual
, Decls body
)
50 : ClassDefinition(INFERENCE_CLASS
,id
,
64 InferenceClass::~InferenceClass() {}
66 ///////////////////////////////////////////////////////////////////////////////
68 // Method to generate the interface for an inference class.
70 ///////////////////////////////////////////////////////////////////////////////
71 void InferenceClass::gen_class_interface (CodeGen
& C
)
75 "%^void operator = (const %s&);%-"
77 "%^static const Node network_table[];"
78 "%^static const RelationTable relation_table[];%-"
81 "%^virtual const char * name_of() const;"
82 "%^void initialise_axioms();%-"
84 "%^virtual void alpha_test (int, int, Fact *);"
85 "%^virtual int beta_test (Join, Fact * []);"
86 "%^virtual void action (RuleId, Fact * []);%-"
88 class_name
, class_name
, class_name
, class_name
);
91 ///////////////////////////////////////////////////////////////////////////////
93 // Forward declarations.
95 ///////////////////////////////////////////////////////////////////////////////
96 Bool
partition(Exp e1
, Exp e2
, int &obj
);
97 Bool
partition(Exps exp
, int &obj
);
98 Bool
partition(LabExps exp
, int &obj
);
99 int partition_inference_rules
100 (int n
, InferenceRule Rs
[], HashTable
& rule_map
, HashTable
& join_map
);
102 ///////////////////////////////////////////////////////////////////////////////
104 // Flatten an expression into conjuncts. Also try to push down negation
105 // as much as possible. Notice that C++ short circuited ands and ors are not
106 // commutative (but they are associative.)
108 ///////////////////////////////////////////////////////////////////////////////
109 Exp
* flatten (Exp exp
, Exp
* cnf
, Bool neg
)
111 #line 89 "infgen.pcc"
112 #line 101 "infgen.pcc"
116 switch (exp
->tag__
) {
117 case a_Exp::tag_BINOPexp
: {
119 #line 100 "infgen.pcc"
121 #line 100 "infgen.pcc"
124 if (_less_string(((Exp_BINOPexp
*)exp
)->_1
,"==")) {
125 if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"!=")) {
127 #line 99 "infgen.pcc"
129 #line 99 "infgen.pcc"
133 #line 99 "infgen.pcc"
134 *cnf
= BINOPexp("==",((Exp_BINOPexp
*)exp
)->_2
,((Exp_BINOPexp
*)exp
)->_3
); return cnf
+1;
135 #line 99 "infgen.pcc"
139 #line 100 "infgen.pcc"
140 *cnf
= PREFIXexp("!",exp
); return cnf
+1;
141 #line 100 "infgen.pcc"
144 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"&&")) {
146 #line 92 "infgen.pcc"
148 #line 92 "infgen.pcc"
152 #line 92 "infgen.pcc"
153 cnf
= flatten(((Exp_BINOPexp
*)exp
)->_2
,cnf
,neg
); exp
= ((Exp_BINOPexp
*)exp
)->_3
;
154 #line 92 "infgen.pcc"
158 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"<")) {
160 #line 96 "infgen.pcc"
162 #line 96 "infgen.pcc"
166 #line 96 "infgen.pcc"
167 *cnf
= BINOPexp(">=",((Exp_BINOPexp
*)exp
)->_2
,((Exp_BINOPexp
*)exp
)->_3
); return cnf
+1;
168 #line 96 "infgen.pcc"
172 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"<=")) {
174 #line 97 "infgen.pcc"
176 #line 97 "infgen.pcc"
180 #line 97 "infgen.pcc"
181 *cnf
= BINOPexp(">",((Exp_BINOPexp
*)exp
)->_2
,((Exp_BINOPexp
*)exp
)->_3
); return cnf
+1;
182 #line 97 "infgen.pcc"
188 if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"==")) {
190 #line 98 "infgen.pcc"
192 #line 98 "infgen.pcc"
196 #line 98 "infgen.pcc"
197 *cnf
= BINOPexp("!=",((Exp_BINOPexp
*)exp
)->_2
,((Exp_BINOPexp
*)exp
)->_3
); return cnf
+1;
198 #line 98 "infgen.pcc"
202 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,">")) {
204 #line 94 "infgen.pcc"
206 #line 94 "infgen.pcc"
210 #line 94 "infgen.pcc"
211 *cnf
= BINOPexp("<=",((Exp_BINOPexp
*)exp
)->_2
,((Exp_BINOPexp
*)exp
)->_3
); return cnf
+1;
212 #line 94 "infgen.pcc"
216 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,">=")) {
218 #line 95 "infgen.pcc"
220 #line 95 "infgen.pcc"
224 #line 95 "infgen.pcc"
225 *cnf
= BINOPexp("<",((Exp_BINOPexp
*)exp
)->_2
,((Exp_BINOPexp
*)exp
)->_3
); return cnf
+1;
226 #line 95 "infgen.pcc"
230 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"||")) {
232 #line 93 "infgen.pcc"
234 #line 93 "infgen.pcc"
238 #line 93 "infgen.pcc"
239 cnf
= flatten(((Exp_BINOPexp
*)exp
)->_2
,cnf
,neg
); exp
= ((Exp_BINOPexp
*)exp
)->_3
;
240 #line 93 "infgen.pcc"
248 if (_less_string(((Exp_BINOPexp
*)exp
)->_1
,"==")) {
249 if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"!=")) {
251 #line 99 "infgen.pcc"
253 #line 99 "infgen.pcc"
258 #line 101 "infgen.pcc"
259 *cnf
= exp
; return cnf
+1;
260 #line 101 "infgen.pcc"
263 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"&&")) {
265 #line 92 "infgen.pcc"
267 #line 92 "infgen.pcc"
272 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"<")) {
274 #line 96 "infgen.pcc"
276 #line 96 "infgen.pcc"
281 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"<=")) {
283 #line 97 "infgen.pcc"
285 #line 97 "infgen.pcc"
292 if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"==")) {
294 #line 98 "infgen.pcc"
296 #line 98 "infgen.pcc"
301 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,">")) {
303 #line 94 "infgen.pcc"
305 #line 94 "infgen.pcc"
310 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,">=")) {
312 #line 95 "infgen.pcc"
314 #line 95 "infgen.pcc"
319 else if (_equal_string(((Exp_BINOPexp
*)exp
)->_1
,"||")) {
321 #line 93 "infgen.pcc"
323 #line 93 "infgen.pcc"
332 case a_Exp::tag_PREFIXexp
: {
334 #line 100 "infgen.pcc"
336 #line 100 "infgen.pcc"
339 if (_equal_string(((Exp_PREFIXexp
*)exp
)->_1
,"!")) {
341 #line 91 "infgen.pcc"
342 exp
= ((Exp_PREFIXexp
*)exp
)->_2
; neg
= !neg
;
343 #line 91 "infgen.pcc"
348 if (_equal_string(((Exp_PREFIXexp
*)exp
)->_1
,"!")) { goto L12
; }
352 case a_Exp::tag_MARKEDexp
: {
353 #line 90 "infgen.pcc"
354 exp
= ((Exp_MARKEDexp
*)exp
)->_2
;
355 #line 90 "infgen.pcc"
360 #line 100 "infgen.pcc"
362 #line 100 "infgen.pcc"
371 #line 102 "infgen.pcc"
372 #line 102 "infgen.pcc"
376 ///////////////////////////////////////////////////////////////////////////////
378 // Returns true if an expression involves only one object.
379 // Also returns the highest numbered object involved.
380 // As a convention, the object number is -1 if the expression is a constant.
382 ///////////////////////////////////////////////////////////////////////////////
383 Bool
partition(Exp exp
, int &obj
)
385 #line 113 "infgen.pcc"
386 #line 140 "infgen.pcc"
389 switch (exp
->tag__
) {
390 case a_Exp::tag_RELexp
: {
391 #line 124 "infgen.pcc"
392 obj
= ((Exp_RELexp
*)exp
)->RELexp
; return true;
393 #line 124 "infgen.pcc"
395 case a_Exp::tag_DOTexp
: {
396 #line 119 "infgen.pcc"
397 return partition(((Exp_DOTexp
*)exp
)->_1
,obj
);
398 #line 119 "infgen.pcc"
400 case a_Exp::tag_SELECTORexp
: {
401 #line 118 "infgen.pcc"
402 return partition(((Exp_SELECTORexp
*)exp
)->_1
,obj
);
403 #line 118 "infgen.pcc"
405 case a_Exp::tag_DEREFexp
: {
406 #line 117 "infgen.pcc"
407 return partition(((Exp_DEREFexp
*)exp
)->DEREFexp
,obj
);
408 #line 117 "infgen.pcc"
410 case a_Exp::tag_ARROWexp
: {
411 #line 120 "infgen.pcc"
412 return partition(((Exp_ARROWexp
*)exp
)->_1
,obj
);
413 #line 120 "infgen.pcc"
415 case a_Exp::tag_INDEXexp
: {
416 #line 126 "infgen.pcc"
417 return partition(((Exp_INDEXexp
*)exp
)->_1
,((Exp_INDEXexp
*)exp
)->_2
,obj
);
418 #line 126 "infgen.pcc"
420 case a_Exp::tag_BINOPexp
: {
421 #line 128 "infgen.pcc"
422 return partition(((Exp_BINOPexp
*)exp
)->_2
,((Exp_BINOPexp
*)exp
)->_3
,obj
);
423 #line 128 "infgen.pcc"
425 case a_Exp::tag_PREFIXexp
: {
426 #line 115 "infgen.pcc"
427 return partition(((Exp_PREFIXexp
*)exp
)->_2
,obj
);
428 #line 115 "infgen.pcc"
430 case a_Exp::tag_POSTFIXexp
: {
431 #line 116 "infgen.pcc"
432 return partition(((Exp_POSTFIXexp
*)exp
)->_2
,obj
);
433 #line 116 "infgen.pcc"
435 case a_Exp::tag_APPexp
: {
436 #line 125 "infgen.pcc"
437 return partition(((Exp_APPexp
*)exp
)->_1
,((Exp_APPexp
*)exp
)->_2
,obj
);
438 #line 125 "infgen.pcc"
440 case a_Exp::tag_ASSIGNexp
: {
441 #line 127 "infgen.pcc"
442 return partition(((Exp_ASSIGNexp
*)exp
)->_1
,((Exp_ASSIGNexp
*)exp
)->_2
,obj
);
443 #line 127 "infgen.pcc"
445 case a_Exp::tag_IFexp
: {
446 #line 138 "infgen.pcc"
448 #line 138 "infgen.pcc"
449 #line 138 "infgen.pcc"
450 list_1_(((Exp_IFexp
*)exp
)->_1
,list_1_(((Exp_IFexp
*)exp
)->_2
,list_1_(((Exp_IFexp
*)exp
)->_3
)))
451 #line 138 "infgen.pcc"
452 #line 138 "infgen.pcc"
454 #line 138 "infgen.pcc"
456 case a_Exp::tag_TUPLEexp
: {
457 #line 132 "infgen.pcc"
458 return partition(((Exp_TUPLEexp
*)exp
)->TUPLEexp
,obj
);
459 #line 132 "infgen.pcc"
461 case a_Exp::tag_RECORDexp
: {
462 #line 133 "infgen.pcc"
463 return partition(((Exp_RECORDexp
*)exp
)->RECORDexp
,obj
);
464 #line 133 "infgen.pcc"
466 case a_Exp::tag_LISTexp
: {
467 #line 136 "infgen.pcc"
469 #line 136 "infgen.pcc"
470 #line 136 "infgen.pcc"
471 list_1_(((Exp_LISTexp
*)exp
)->_4
,((Exp_LISTexp
*)exp
)->_3
)
472 #line 136 "infgen.pcc"
473 #line 136 "infgen.pcc"
475 #line 136 "infgen.pcc"
477 case a_Exp::tag_VECTORexp
: {
478 #line 135 "infgen.pcc"
479 return partition(((Exp_VECTORexp
*)exp
)->_2
,obj
);
480 #line 135 "infgen.pcc"
482 case a_Exp::tag_CONSexp
: {
483 #line 121 "infgen.pcc"
484 return partition(((Exp_CONSexp
*)exp
)->_3
,obj
);
485 #line 121 "infgen.pcc"
487 case a_Exp::tag_CASTexp
: {
488 #line 123 "infgen.pcc"
489 return partition(((Exp_CASTexp
*)exp
)->_2
,obj
);
490 #line 123 "infgen.pcc"
492 case a_Exp::tag_EQexp
: {
493 #line 129 "infgen.pcc"
494 return partition(((Exp_EQexp
*)exp
)->_2
,((Exp_EQexp
*)exp
)->_3
,obj
);
495 #line 129 "infgen.pcc"
497 case a_Exp::tag_UNIFYexp
: {
498 #line 130 "infgen.pcc"
499 return partition(((Exp_UNIFYexp
*)exp
)->_2
,((Exp_UNIFYexp
*)exp
)->_3
,obj
);
500 #line 130 "infgen.pcc"
502 case a_Exp::tag_LTexp
: {
503 #line 131 "infgen.pcc"
504 return partition(((Exp_LTexp
*)exp
)->_2
,((Exp_LTexp
*)exp
)->_3
,obj
);
505 #line 131 "infgen.pcc"
507 case a_Exp::tag_HASHexp
: {
508 #line 122 "infgen.pcc"
509 return partition(((Exp_HASHexp
*)exp
)->_2
,obj
);
510 #line 122 "infgen.pcc"
512 case a_Exp::tag_SENDexp
: {
513 #line 134 "infgen.pcc"
514 return partition(((Exp_SENDexp
*)exp
)->_2
,obj
);
515 #line 134 "infgen.pcc"
517 case a_Exp::tag_SETLexp
: {
518 #line 137 "infgen.pcc"
519 return partition(((Exp_SETLexp
*)exp
)->_2
,obj
);
520 #line 137 "infgen.pcc"
522 case a_Exp::tag_MARKEDexp
: {
523 #line 114 "infgen.pcc"
524 return partition(((Exp_MARKEDexp
*)exp
)->_2
,obj
);
525 #line 114 "infgen.pcc"
527 case a_Exp::tag_LITERALexp
:
528 case a_Exp::tag_IDexp
: {
530 #line 139 "infgen.pcc"
531 obj
= -1; return true;
532 #line 139 "infgen.pcc"
535 #line 140 "infgen.pcc"
536 bug("partition: %e", exp
); return false;
537 #line 140 "infgen.pcc"
542 #line 141 "infgen.pcc"
543 #line 141 "infgen.pcc"
547 ///////////////////////////////////////////////////////////////////////////////
549 // Categorize two expressions.
551 ///////////////////////////////////////////////////////////////////////////////
552 Bool
partition(Exp e1
, Exp e2
, int &obj
) { return partition(
553 #line 149 "infgen.pcc"
554 #line 149 "infgen.pcc"
555 list_1_(e1
,list_1_(e2
))
556 #line 149 "infgen.pcc"
557 #line 149 "infgen.pcc"
560 ///////////////////////////////////////////////////////////////////////////////
562 // Categorize an list of expressions.
564 ///////////////////////////////////////////////////////////////////////////////
565 Bool
partition(Exps es
, int &obj
)
570 if (! partition(e
,obj1
) || (obj
>= 0 && obj1
>= 0 && obj1
!= obj
))
572 if (obj1
> obj
) obj
= obj1
;
577 ///////////////////////////////////////////////////////////////////////////////
579 // Categorize an labeled list of expressions.
581 ///////////////////////////////////////////////////////////////////////////////
582 Bool
partition(LabExps es
, int &obj
)
585 for_each(LabExp
, e
, es
) {
587 if (! partition(e
.exp
,obj1
) || (obj
>= 0 && obj1
>= 0 && obj1
!= obj
))
589 if (obj1
> obj
) obj
= obj1
;
594 ///////////////////////////////////////////////////////////////////////////////
595 // Create an and expression.
596 ///////////////////////////////////////////////////////////////////////////////
597 Exp
mkandexp(Exp a
, Exp b
)
598 { if (a
== NOexp
) return b
;
599 if (b
== NOexp
) return a
;
600 return BINOPexp("&&",a
, b
);
603 ///////////////////////////////////////////////////////////////////////////////
605 // Decompose guard expressions in conjunctive normal form into
606 // selections and (theta) joins.
608 // We are given $n$ objects and $n$ booleans expressions.
609 // We want to decompose these $n$ expressions into (at most)
610 // $n$ single object selects and (at most) $n$ joins.
612 ///////////////////////////////////////////////////////////////////////////////
613 int decompose (int n
, Exp exps
[], Exp selects
[], Exp joins
[])
616 for (i
= 0; i
< n
; i
++) selects
[i
] = joins
[i
] = NOexp
;
617 for (i
= 0; i
< n
; i
++) {
618 debug_msg ("decomposing: %e\n", exps
[i
]);
619 Exp cnf
[MAX_CONJUNCTS
]; // assume we don't have more than 256 conjuncts.
620 Exp
* last
= flatten(exps
[i
], cnf
, false); // flatten expression.
621 int conjuncts
= last
- cnf
;
622 if (conjuncts
> MAX_CONJUNCTS
)
623 bug ("Conjuncts exceeded %i in decompose()", MAX_CONJUNCTS
);
624 for (int j
= 0; j
< conjuncts
; j
++) {
626 //////////////////////////////////////////////////////////////////////
627 // Checks whether the conjunct depends on only one variable.
628 // If so it can be executed as a guard during pattern matching.
629 // Otherwise, it is a join and must be executed by the
630 // RETE engine. In any case hoist the conjunct as far up as possible
631 // to minimize the sizes of intermediate relations.
632 //////////////////////////////////////////////////////////////////////
633 debug_msg ("partitioning: %e\n", cnf
[j
]);
634 Bool depends_on_one_variable
= partition(cnf
[j
],obj
);
635 if (obj
< 0) obj
= 0;
636 if (depends_on_one_variable
) { // expression is a select
637 if (selects
[obj
] == NOexp
) selects
[obj
] = cnf
[j
];
638 else selects
[obj
] = mkandexp(selects
[obj
],cnf
[j
]);
639 debug_msg ("select: %e\n", cnf
[j
]);
640 } else { // expression is a join
641 if (joins
[obj
] == NOexp
) joins
[obj
] = cnf
[j
];
642 else joins
[obj
] = mkandexp(joins
[obj
],cnf
[j
]);
643 debug_msg ("join: %e\n", cnf
[j
]);
645 if (obj
> max_object
) max_object
= obj
;
651 ///////////////////////////////////////////////////////////////////////////////
653 // Decompose a set of pattern matching rules and extract out the joins
654 // from each of the guards.
656 ///////////////////////////////////////////////////////////////////////////////
657 int decompose (MatchRules rules
, Exp joins
[], Exp guard_exp
)
658 { Exp guards
[MAX_INFERENCE_RULE_ARITY
];
659 Exp selects
[MAX_INFERENCE_RULE_ARITY
];
662 { for_each (MatchRule
, r
, rules
)
664 #line 254 "infgen.pcc"
665 #line 255 "infgen.pcc"
667 #line 255 "infgen.pcc"
669 #line 255 "infgen.pcc"
671 #line 255 "infgen.pcc"
672 #line 255 "infgen.pcc"
676 guards
[n
++] = guard_exp
;
678 if (n
>= MAX_INFERENCE_RULE_ARITY
)
679 bug ("%Linference rule arity exceeds %i in decompose()",
680 MAX_INFERENCE_RULE_ARITY
);
682 // take all the guard expressions and decompose them.
683 int max_object
= decompose(n
, guards
, selects
, joins
);
685 // rebuild the guards. Now they must all involve at most one
688 for_each (MatchRule
, r
, rules
)
690 #line 271 "infgen.pcc"
691 #line 272 "infgen.pcc"
693 #line 272 "infgen.pcc"
694 r
->_3
= selects
[i
]; i
++;
695 #line 272 "infgen.pcc"
697 #line 272 "infgen.pcc"
698 #line 272 "infgen.pcc"
706 ///////////////////////////////////////////////////////////////////////////////
708 // Top level method to compile a set of inference rules.
710 ///////////////////////////////////////////////////////////////////////////////
711 void InferenceCompiler::gen_inference_rules(Id id
, InferenceRules rules
)
712 { MemPoolMark marker
= mem_pool
.getMark(); // get heap marker
714 ////////////////////////////////////////////////////////////////////////////
715 // Mapping from type id to list of rules.
716 ////////////////////////////////////////////////////////////////////////////
717 HashTable
rule_map(string_hash
, string_equal
, 129);
718 HashTable
join_map(integer_hash
, integer_equal
);
720 ////////////////////////////////////////////////////////////////////////////
721 // Map the rules into an array
722 ////////////////////////////////////////////////////////////////////////////
723 int n
= length(rules
);
725 InferenceRule
* Rs
= (InferenceRule
*)mem_pool
[n
* sizeof(InferenceRule
)];
726 { int i
= 0; for_each (InferenceRule
,r
,rules
) Rs
[i
++] = r
; }
728 max_arity
= partition_inference_rules(n
, Rs
, rule_map
, join_map
);
729 pr ("const char * %s::name_of() const { return \"%s\"; }\n\n", id
, id
);
730 gen_alpha_tests (id
, max_arity
, rule_map
);
731 gen_beta_tests (id
, n
, Rs
, join_map
);
732 gen_inference_actions (id
, rules
);
733 gen_dispatch_table (id
, rule_map
);
734 int m
= gen_network_table (id
, n
, Rs
, join_map
);
735 gen_inference_axioms (id
, rules
);
736 gen_inference_constructor (id
, m
, rule_map
);
738 ////////////////////////////////////////////////////////////////////////////
740 ////////////////////////////////////////////////////////////////////////////
741 mem_pool
.setMark(marker
); // reclaim memory
744 ///////////////////////////////////////////////////////////////////////////////
746 // Method to partition the left hand side of each inference rule according
747 // to the type of the pattern. Patterns of the same type are grouped
748 // together and compiled using the pattern matching compiler. The steps are:
749 // (a) Decompose the guard expression into selections (predicates on a
750 // single object object) and joins (predicates on 2 or more objects.)
751 // Both of these are hoisted upward as much as possible.
752 // (b) Perform type inference on the pattern.
753 // (c) Enter all the rules of the same type in the same entry of the rule
756 ///////////////////////////////////////////////////////////////////////////////
757 int partition_inference_rules
758 (int n
, InferenceRule Rs
[], HashTable
& rule_map
, HashTable
& join_map
)
760 int node_number
= 0; // node number in network table.
761 for (int rule_no
= 0; rule_no
< n
; rule_no
++)
762 { int positive_clauses
= 0;
763 int negative_clauses
= 0;
765 #line 337 "infgen.pcc"
766 #line 387 "infgen.pcc"
768 InferenceRule _V1
= Rs
[rule_no
];
769 #line 339 "infgen.pcc"
770 int object_count
= 0;
771 Exp joins
[MAX_INFERENCE_RULE_ARITY
];
772 // decompose multi-object test
773 int n
= decompose (_V1
->_1
, joins
, _V1
->_2
);
775 for_each (MatchRule
, r
, _V1
->_1
)
778 #line 346 "infgen.pcc"
779 #line 380 "infgen.pcc"
781 #line 348 "infgen.pcc"
783 #line 348 "infgen.pcc"
784 #line 378 "infgen.pcc"
786 Ty _V2
= (r
->ty
= type_of(r
->_2
));
788 switch (_V2
->tag__
) {
789 case a_Ty::tag_TYCONty
: {
790 if (boxed(((Ty_TYCONty
*)_V2
)->_1
)) {
791 switch (((Ty_TYCONty
*)_V2
)->_1
->tag__
) {
792 case a_TyCon::tag_DATATYPEtycon
: {
794 #line 350 "infgen.pcc"
795 (((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)_V2
)->_1
)->qualifiers
& QUALrelation
)
796 #line 350 "infgen.pcc"
799 #line 351 "infgen.pcc"
801 HashTable::Entry
* e
= rule_map
.lookup(((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)_V2
)->_1
)->id
);
802 if (e
) rule_map
.insert(((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)_V2
)->_1
)->id
,
803 #line 353 "infgen.pcc"
804 #line 353 "infgen.pcc"
805 list_1_(r
,MatchRules(rule_map
.value(e
)))
806 #line 353 "infgen.pcc"
807 #line 353 "infgen.pcc"
809 else rule_map
.insert(((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)_V2
)->_1
)->id
,
810 #line 354 "infgen.pcc"
811 #line 354 "infgen.pcc"
813 #line 354 "infgen.pcc"
814 #line 354 "infgen.pcc"
816 r
->rule_number
= node_number
;
817 if (joins
[i
] != NOexp
) {
818 HashTable::Entry
* e
=
819 join_map
.lookup((HashTable::Key
)node_number
);
821 join_map
.insert((HashTable::Key
)node_number
,
822 BINOPexp("&&",(Exp
)join_map
.value(e
),joins
[i
]));
824 join_map
.insert((HashTable::Key
)node_number
,
828 if (positive_clauses
== 0 && !r
->negated
) {
830 #line 368 "infgen.pcc"
831 #line 368 "infgen.pcc"
832 list_1_(INJECTdecl(node_number
,LEFTdirection
))
833 #line 368 "infgen.pcc"
834 #line 368 "infgen.pcc"
838 #line 370 "infgen.pcc"
839 #line 370 "infgen.pcc"
840 list_1_(INJECTdecl(node_number
,RIGHTdirection
))
841 #line 370 "infgen.pcc"
842 #line 370 "infgen.pcc"
846 if (r
->negated
) negative_clauses
++;
847 else positive_clauses
++;
849 #line 375 "infgen.pcc"
853 #line 378 "infgen.pcc"
854 error("%Lnon-relation type %T in pattern: %p\n", _V2
, r
->_2
);
855 #line 378 "infgen.pcc"
858 default: { goto L15
; } break;
862 default: { goto L15
; } break;
866 #line 379 "infgen.pcc"
867 #line 379 "infgen.pcc"
870 #line 380 "infgen.pcc"
872 #line 381 "infgen.pcc"
873 #line 381 "infgen.pcc"
879 if (max_arity
< object_count
) max_arity
= object_count
;
881 #line 387 "infgen.pcc"
883 #line 388 "infgen.pcc"
884 #line 388 "infgen.pcc"
890 ///////////////////////////////////////////////////////////////////////////////
892 // Method to generate the alpha (single object) tests.
894 ///////////////////////////////////////////////////////////////////////////////
895 void InferenceCompiler::gen_alpha_tests
896 (Id id
, int max_arity
, HashTable
& rule_map
)
897 { pr ("%^%/%^// Single object tests for inference class %s%^%/"
898 "%^void %s::alpha_test(int predicate__, int i__, Fact * fact__)"
901 "%^switch (predicate__) {%+", id
, id
, max_arity
);
902 { Bool save
= same_selectors
;
903 same_selectors
= true;
905 foreach_entry(e
, rule_map
)
906 { Id ty_name
= (Id
)rule_map
.key(e
);
907 MatchRules rules
= (MatchRules
)rule_map
.value(e
);
909 "%^%s _0 = (%s)(f__[0] = fact__);",
910 type_number
, ty_name
, ty_name
);
912 #line 414 "infgen.pcc"
913 #line 414 "infgen.pcc"
915 #line 414 "infgen.pcc"
916 #line 414 "infgen.pcc"
917 , rules
, MATCHall
| MATCHnocheck
);
921 same_selectors
= save
;
927 ///////////////////////////////////////////////////////////////////////////////
929 // Method to generate the beta tests(joins)
931 ///////////////////////////////////////////////////////////////////////////////
932 void InferenceCompiler::gen_beta_tests
933 (Id id
, int n
, InferenceRule rules
[], HashTable
& join_map
)
934 { pr ("%^%/%^// Joins for inference class %s%^%/"
935 "%^int %s::beta_test(Join join__, Fact * f__[])"
937 "%^switch (join__) {%+", id
, id
);
939 for (int i
= 0; i
< n
; i
++)
941 #line 437 "infgen.pcc"
942 #line 460 "infgen.pcc"
944 InferenceRule _V3
= rules
[i
];
945 #line 439 "infgen.pcc"
946 for(MatchRules rs
= _V3
->_1
; rs
; rs
= rs
->_2
)
948 #line 440 "infgen.pcc"
949 #line 440 "infgen.pcc"
951 #line 440 "infgen.pcc"
952 #line 440 "infgen.pcc"
954 rs
->_1
->rule_number
!= rs
->_2
->_1
->rule_number
)
955 { MatchRule r
= rs
->_1
;
956 int rule_no
= r
->rule_number
;
957 HashTable::Entry
* e
=
958 join_map
.lookup((HashTable::Key
)rule_no
);
960 { Exp join
= (Exp
)join_map
.value(e
);
962 pr ("%^case %i: {%+", rule_no
);
963 for_each (MatchRule
, mr
, _V3
->_1
)
964 { pr ("%^%t _%i = (%t)f__[%i];",
965 mr
->ty
, "", j
, mr
->ty
, "", j
);
969 pr ("%^return %e;%-%^}", join
);
974 #line 460 "infgen.pcc"
976 #line 461 "infgen.pcc"
977 #line 461 "infgen.pcc"
981 pr ("%^default: return 0;"
986 ///////////////////////////////////////////////////////////////////////////////
988 // Generate the dispatch table.
990 ///////////////////////////////////////////////////////////////////////////////
991 void InferenceCompiler::gen_dispatch_table(Id id
, HashTable
& rule_map
)
992 { pr ("%^%/%^// Dispatch table for inference class %s%^%/"
993 "%^const %s::RelationTable %s::relation_table[] = {%+",
995 { int type_number
= 1;
997 foreach_entry(e
, rule_map
)
998 { Id ty_name
= (Id
)rule_map
.key(e
);
1000 pr ("%^{ &a_%s::relation_tag, %i, \"%s\" }",
1001 ty_name
, type_number
, ty_name
);
1009 ///////////////////////////////////////////////////////////////////////////////
1011 // Generate the network table.
1013 ///////////////////////////////////////////////////////////////////////////////
1014 int InferenceCompiler::gen_network_table
1015 (Id id
, int n
, InferenceRule rules
[], HashTable
& join_table
)
1016 { pr ("%^%/%^// Network table for inference class %s%^%/"
1017 "%^const %s::Node %s::network_table[] = {%+",
1022 for (int i
= 0; i
< n
; i
++)
1024 #line 506 "infgen.pcc"
1025 #line 532 "infgen.pcc"
1027 InferenceRule _V4
= rules
[i
];
1028 #line 508 "infgen.pcc"
1029 int max_arity
= length(_V4
->_1
);
1030 int last_rule_number
= -1;
1032 for_each (MatchRule
, r
, _V4
->_1
)
1033 { if (last_rule_number
!= r
->rule_number
1034 && (max_arity
> 1 || r
->negated
) ) {
1035 if (comma
) pr (",");
1036 Id typ
= r
->negated
? "Not" : "And";
1038 join_table
.contains((HashTable::Key
)r
->rule_number
)
1039 ? r
->rule_number
: 0;
1040 pr ("%^{ %i, %i, ReteNet::Node::%s, %i, %i } /* %i */",
1041 arity
, max_arity
, typ
, join
, r
->rule_number
+ 1, entries
);
1046 last_rule_number
= r
->rule_number
;
1048 if (comma
) pr (",");
1049 pr ("%^{ 0, %i, ReteNet::Node::Bot, %i, %i } /* %i */",
1050 max_arity
, 0, i
, entries
);
1054 #line 532 "infgen.pcc"
1056 #line 533 "infgen.pcc"
1057 #line 533 "infgen.pcc"
1066 ///////////////////////////////////////////////////////////////////////////////
1068 // Generate the axioms of the inference class.
1070 ///////////////////////////////////////////////////////////////////////////////
1071 void InferenceCompiler::gen_inference_axioms(Id id
, InferenceRules rules
)
1073 pr ("%^%/%^// Axioms for inference class %s%^%/"
1074 "%^void %s::initialise_axioms()"
1077 for_each(InferenceRule
, r
, rules
)
1079 #line 553 "infgen.pcc"
1080 #line 556 "infgen.pcc"
1082 if (r
->_1
) {} else {
1083 #line 554 "infgen.pcc"
1084 gen_conclusions(r
->_3
);
1085 #line 554 "infgen.pcc"
1088 #line 556 "infgen.pcc"
1089 #line 556 "infgen.pcc"
1095 ///////////////////////////////////////////////////////////////////////////////
1097 // Generate the action routine of the inference class
1099 ///////////////////////////////////////////////////////////////////////////////
1100 void InferenceCompiler::gen_inference_actions(Id id
, InferenceRules rules
)
1102 pr ("%^%/%^// Actions for inference class %s%^%/"
1103 "%^void %s::action(%s::RuleId r__, Fact * f__[])"
1105 "%^switch (r__) {%+",
1109 for_each(InferenceRule
, r
, rules
)
1111 #line 576 "infgen.pcc"
1112 #line 588 "infgen.pcc"
1115 #line 578 "infgen.pcc"
1116 pr ("%^case %i: {%+", rule_no
);
1118 for_each (MatchRule
, mr
, r
->_1
)
1119 { pr ("%^%t _%i = (%t)f__[%i];", mr
->ty
, "", i
, mr
->ty
, "", i
);
1122 gen_conclusions(r
->_3
);
1123 pr ("%-%^} break;");
1125 #line 586 "infgen.pcc"
1128 #line 588 "infgen.pcc"
1129 #line 588 "infgen.pcc"
1137 ///////////////////////////////////////////////////////////////////////////////
1139 // Generate the conclusions of the inference class.
1141 ///////////////////////////////////////////////////////////////////////////////
1142 void InferenceCompiler::gen_conclusions(Conclusions cs
)
1143 { for_each (Conclusion
, c
, cs
) gen_conclusion(c
); }
1145 ///////////////////////////////////////////////////////////////////////////////
1147 // Generate one conclusion of the inference class.
1149 ///////////////////////////////////////////////////////////////////////////////
1150 void InferenceCompiler::gen_conclusion(Conclusion c
)
1152 #line 609 "infgen.pcc"
1153 #line 612 "infgen.pcc"
1155 switch (untagp(c
)) {
1156 case a_Conclusion::tag_ASSERTaction
: {
1157 #line 610 "infgen.pcc"
1158 pr ("%^assert_fact(%e);\n", ((Conclusion_ASSERTaction
*)c
)->ASSERTaction
);
1159 #line 610 "infgen.pcc"
1161 case a_Conclusion::tag_RETRACTaction
: {
1162 #line 611 "infgen.pcc"
1163 pr ("%^retract_fact(%e);\n", ((Conclusion_RETRACTaction
*)derefp(c
))->RETRACTaction
);
1164 #line 611 "infgen.pcc"
1167 #line 612 "infgen.pcc"
1168 pr ("%^%&", ((Conclusion_STMTaction
*)derefp(c
))->STMTaction
);
1169 #line 612 "infgen.pcc"
1173 #line 613 "infgen.pcc"
1174 #line 613 "infgen.pcc"
1178 ///////////////////////////////////////////////////////////////////////////////
1180 // Generate the constructor of the inference class.
1182 ///////////////////////////////////////////////////////////////////////////////
1183 void InferenceCompiler::gen_inference_constructor
1184 (Id id
, int entries
, HashTable
& rule_map
)
1186 pr ("%^%/%^// Constructor for inference class %s%^%/"
1188 "%^: Rete(%i,%s::network_table,%i,%s::relation_table)%+"
1189 "%^{ initialise_axioms(); }%-%-\n\n",
1191 entries
, id
, rule_map
.size(), id
);
1194 ///////////////////////////////////////////////////////////////////////////////
1196 // Generate the interface of a relation object.
1198 ///////////////////////////////////////////////////////////////////////////////
1199 void DatatypeClass::generate_inference_interface(CodeGen
& C
)
1201 if (this != root
) return;
1205 "%^// Inference methods"
1208 "%^static RelTag relation_tag;"
1209 "%^virtual RelTag get_tag() const;"
1213 ///////////////////////////////////////////////////////////////////////////////
1215 // Generate the implementation of a relation object.
1217 ///////////////////////////////////////////////////////////////////////////////
1218 void DatatypeClass::generate_inference_implementation
1219 (CodeGen
& C
, Tys tys
, DefKind k
)
1221 if (this != root
) return;
1225 "%^// Relation datatype %s%P"
1228 "%^Fact::RelTag %s%P::relation_tag = 0;"
1229 "%^static InitialiseFact %s_dummy__(%s%P::relation_tag);"
1230 "%^Fact::RelTag %s%P::get_tag() const"
1231 " { return %s%P::relation_tag; }\n \n",
1232 root
->datatype_name
, tys
,
1234 DatatypeCompiler::temp_vars
.new_label(), class_name
, tys
,
1239 #line 677 "infgen.pcc"
1241 ------------------------------- Statistics -------------------------------
1242 Merge matching rules = yes
1243 Number of DFA nodes merged = 169
1244 Number of ifs generated = 46
1245 Number of switches generated = 5
1246 Number of labels = 14
1247 Number of gotos = 36
1248 Adaptive matching = enabled
1249 Fast string matching = disabled
1250 Inline downcasts = enabled
1251 --------------------------------------------------------------------------