clipsruby 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/clipsruby/agenda.c +1373 -0
- data/ext/clipsruby/agenda.h +169 -0
- data/ext/clipsruby/analysis.c +1142 -0
- data/ext/clipsruby/analysis.h +61 -0
- data/ext/clipsruby/argacces.c +526 -0
- data/ext/clipsruby/argacces.h +77 -0
- data/ext/clipsruby/bload.c +884 -0
- data/ext/clipsruby/bload.h +94 -0
- data/ext/clipsruby/bmathfun.c +557 -0
- data/ext/clipsruby/bmathfun.h +66 -0
- data/ext/clipsruby/bsave.c +634 -0
- data/ext/clipsruby/bsave.h +130 -0
- data/ext/clipsruby/classcom.c +976 -0
- data/ext/clipsruby/classcom.h +115 -0
- data/ext/clipsruby/classexm.c +1376 -0
- data/ext/clipsruby/classexm.h +97 -0
- data/ext/clipsruby/classfun.c +1392 -0
- data/ext/clipsruby/classfun.h +164 -0
- data/ext/clipsruby/classinf.c +1245 -0
- data/ext/clipsruby/classinf.h +94 -0
- data/ext/clipsruby/classini.c +843 -0
- data/ext/clipsruby/classini.h +75 -0
- data/ext/clipsruby/classpsr.c +957 -0
- data/ext/clipsruby/classpsr.h +73 -0
- data/ext/clipsruby/clips.h +133 -0
- data/ext/clipsruby/clipsruby.c +619 -0
- data/ext/clipsruby/clsltpsr.c +931 -0
- data/ext/clipsruby/clsltpsr.h +72 -0
- data/ext/clipsruby/commline.c +1217 -0
- data/ext/clipsruby/commline.h +131 -0
- data/ext/clipsruby/conscomp.c +1593 -0
- data/ext/clipsruby/conscomp.h +150 -0
- data/ext/clipsruby/constant.h +264 -0
- data/ext/clipsruby/constrct.c +1090 -0
- data/ext/clipsruby/constrct.h +216 -0
- data/ext/clipsruby/constrnt.c +554 -0
- data/ext/clipsruby/constrnt.h +132 -0
- data/ext/clipsruby/crstrtgy.c +1088 -0
- data/ext/clipsruby/crstrtgy.h +85 -0
- data/ext/clipsruby/cstrcbin.c +185 -0
- data/ext/clipsruby/cstrcbin.h +61 -0
- data/ext/clipsruby/cstrccmp.h +43 -0
- data/ext/clipsruby/cstrccom.c +1791 -0
- data/ext/clipsruby/cstrccom.h +115 -0
- data/ext/clipsruby/cstrcpsr.c +835 -0
- data/ext/clipsruby/cstrcpsr.h +97 -0
- data/ext/clipsruby/cstrnbin.c +282 -0
- data/ext/clipsruby/cstrnbin.h +55 -0
- data/ext/clipsruby/cstrnchk.c +826 -0
- data/ext/clipsruby/cstrnchk.h +91 -0
- data/ext/clipsruby/cstrncmp.c +238 -0
- data/ext/clipsruby/cstrncmp.h +57 -0
- data/ext/clipsruby/cstrnops.c +1176 -0
- data/ext/clipsruby/cstrnops.h +47 -0
- data/ext/clipsruby/cstrnpsr.c +1394 -0
- data/ext/clipsruby/cstrnpsr.h +88 -0
- data/ext/clipsruby/cstrnutl.c +564 -0
- data/ext/clipsruby/cstrnutl.h +54 -0
- data/ext/clipsruby/default.c +454 -0
- data/ext/clipsruby/default.h +57 -0
- data/ext/clipsruby/defins.c +971 -0
- data/ext/clipsruby/defins.h +127 -0
- data/ext/clipsruby/developr.c +677 -0
- data/ext/clipsruby/developr.h +69 -0
- data/ext/clipsruby/dffctbin.c +477 -0
- data/ext/clipsruby/dffctbin.h +76 -0
- data/ext/clipsruby/dffctbsc.c +308 -0
- data/ext/clipsruby/dffctbsc.h +72 -0
- data/ext/clipsruby/dffctcmp.c +297 -0
- data/ext/clipsruby/dffctcmp.h +44 -0
- data/ext/clipsruby/dffctdef.c +364 -0
- data/ext/clipsruby/dffctdef.h +104 -0
- data/ext/clipsruby/dffctpsr.c +179 -0
- data/ext/clipsruby/dffctpsr.h +49 -0
- data/ext/clipsruby/dffnxbin.c +520 -0
- data/ext/clipsruby/dffnxbin.h +67 -0
- data/ext/clipsruby/dffnxcmp.c +378 -0
- data/ext/clipsruby/dffnxcmp.h +54 -0
- data/ext/clipsruby/dffnxexe.c +241 -0
- data/ext/clipsruby/dffnxexe.h +58 -0
- data/ext/clipsruby/dffnxfun.c +1192 -0
- data/ext/clipsruby/dffnxfun.h +155 -0
- data/ext/clipsruby/dffnxpsr.c +514 -0
- data/ext/clipsruby/dffnxpsr.h +57 -0
- data/ext/clipsruby/dfinsbin.c +509 -0
- data/ext/clipsruby/dfinsbin.h +66 -0
- data/ext/clipsruby/dfinscmp.c +345 -0
- data/ext/clipsruby/dfinscmp.h +48 -0
- data/ext/clipsruby/drive.c +1191 -0
- data/ext/clipsruby/drive.h +65 -0
- data/ext/clipsruby/emathfun.c +1213 -0
- data/ext/clipsruby/emathfun.h +99 -0
- data/ext/clipsruby/engine.c +1568 -0
- data/ext/clipsruby/engine.h +203 -0
- data/ext/clipsruby/entities.h +276 -0
- data/ext/clipsruby/envrnbld.c +514 -0
- data/ext/clipsruby/envrnbld.h +40 -0
- data/ext/clipsruby/envrnmnt.c +257 -0
- data/ext/clipsruby/envrnmnt.h +112 -0
- data/ext/clipsruby/evaluatn.c +1736 -0
- data/ext/clipsruby/evaluatn.h +211 -0
- data/ext/clipsruby/expressn.c +494 -0
- data/ext/clipsruby/expressn.h +154 -0
- data/ext/clipsruby/exprnbin.c +538 -0
- data/ext/clipsruby/exprnbin.h +60 -0
- data/ext/clipsruby/exprnops.c +564 -0
- data/ext/clipsruby/exprnops.h +67 -0
- data/ext/clipsruby/exprnpsr.c +1112 -0
- data/ext/clipsruby/exprnpsr.h +98 -0
- data/ext/clipsruby/extconf.rb +2 -0
- data/ext/clipsruby/extnfunc.c +1015 -0
- data/ext/clipsruby/extnfunc.h +157 -0
- data/ext/clipsruby/factbin.c +447 -0
- data/ext/clipsruby/factbin.h +56 -0
- data/ext/clipsruby/factbld.c +1035 -0
- data/ext/clipsruby/factbld.h +63 -0
- data/ext/clipsruby/factcmp.c +386 -0
- data/ext/clipsruby/factcmp.h +46 -0
- data/ext/clipsruby/factcom.c +759 -0
- data/ext/clipsruby/factcom.h +80 -0
- data/ext/clipsruby/factfile.c +1761 -0
- data/ext/clipsruby/factfile.h +54 -0
- data/ext/clipsruby/factfun.c +682 -0
- data/ext/clipsruby/factfun.h +77 -0
- data/ext/clipsruby/factgen.c +1305 -0
- data/ext/clipsruby/factgen.h +229 -0
- data/ext/clipsruby/facthsh.c +438 -0
- data/ext/clipsruby/facthsh.h +81 -0
- data/ext/clipsruby/factlhs.c +250 -0
- data/ext/clipsruby/factlhs.h +54 -0
- data/ext/clipsruby/factmch.c +905 -0
- data/ext/clipsruby/factmch.h +68 -0
- data/ext/clipsruby/factmngr.c +3373 -0
- data/ext/clipsruby/factmngr.h +325 -0
- data/ext/clipsruby/factprt.c +498 -0
- data/ext/clipsruby/factprt.h +60 -0
- data/ext/clipsruby/factqpsr.c +796 -0
- data/ext/clipsruby/factqpsr.h +61 -0
- data/ext/clipsruby/factqury.c +1267 -0
- data/ext/clipsruby/factqury.h +112 -0
- data/ext/clipsruby/factrete.c +978 -0
- data/ext/clipsruby/factrete.h +70 -0
- data/ext/clipsruby/factrhs.c +667 -0
- data/ext/clipsruby/factrhs.h +55 -0
- data/ext/clipsruby/filecom.c +353 -0
- data/ext/clipsruby/filecom.h +137 -0
- data/ext/clipsruby/filertr.c +481 -0
- data/ext/clipsruby/filertr.h +94 -0
- data/ext/clipsruby/fileutil.c +1020 -0
- data/ext/clipsruby/fileutil.h +50 -0
- data/ext/clipsruby/generate.c +1079 -0
- data/ext/clipsruby/generate.h +57 -0
- data/ext/clipsruby/genrcbin.c +902 -0
- data/ext/clipsruby/genrcbin.h +69 -0
- data/ext/clipsruby/genrccmp.c +640 -0
- data/ext/clipsruby/genrccmp.h +59 -0
- data/ext/clipsruby/genrccom.c +2017 -0
- data/ext/clipsruby/genrccom.h +119 -0
- data/ext/clipsruby/genrcexe.c +737 -0
- data/ext/clipsruby/genrcexe.h +73 -0
- data/ext/clipsruby/genrcfun.c +890 -0
- data/ext/clipsruby/genrcfun.h +185 -0
- data/ext/clipsruby/genrcpsr.c +1618 -0
- data/ext/clipsruby/genrcpsr.h +80 -0
- data/ext/clipsruby/globlbin.c +458 -0
- data/ext/clipsruby/globlbin.h +71 -0
- data/ext/clipsruby/globlbsc.c +361 -0
- data/ext/clipsruby/globlbsc.h +83 -0
- data/ext/clipsruby/globlcmp.c +330 -0
- data/ext/clipsruby/globlcmp.h +52 -0
- data/ext/clipsruby/globlcom.c +289 -0
- data/ext/clipsruby/globlcom.h +63 -0
- data/ext/clipsruby/globldef.c +1087 -0
- data/ext/clipsruby/globldef.h +151 -0
- data/ext/clipsruby/globlpsr.c +530 -0
- data/ext/clipsruby/globlpsr.h +59 -0
- data/ext/clipsruby/immthpsr.c +431 -0
- data/ext/clipsruby/immthpsr.h +55 -0
- data/ext/clipsruby/incrrset.c +530 -0
- data/ext/clipsruby/incrrset.h +73 -0
- data/ext/clipsruby/inherpsr.c +850 -0
- data/ext/clipsruby/inherpsr.h +52 -0
- data/ext/clipsruby/inscom.c +2076 -0
- data/ext/clipsruby/inscom.h +182 -0
- data/ext/clipsruby/insfile.c +1764 -0
- data/ext/clipsruby/insfile.h +96 -0
- data/ext/clipsruby/insfun.c +1451 -0
- data/ext/clipsruby/insfun.h +134 -0
- data/ext/clipsruby/insmngr.c +2550 -0
- data/ext/clipsruby/insmngr.h +125 -0
- data/ext/clipsruby/insmoddp.c +1041 -0
- data/ext/clipsruby/insmoddp.h +91 -0
- data/ext/clipsruby/insmult.c +804 -0
- data/ext/clipsruby/insmult.h +62 -0
- data/ext/clipsruby/inspsr.c +602 -0
- data/ext/clipsruby/inspsr.h +60 -0
- data/ext/clipsruby/insquery.c +1278 -0
- data/ext/clipsruby/insquery.h +115 -0
- data/ext/clipsruby/insqypsr.c +729 -0
- data/ext/clipsruby/insqypsr.h +63 -0
- data/ext/clipsruby/iofun.c +2045 -0
- data/ext/clipsruby/iofun.h +116 -0
- data/ext/clipsruby/lgcldpnd.c +644 -0
- data/ext/clipsruby/lgcldpnd.h +75 -0
- data/ext/clipsruby/main.c +112 -0
- data/ext/clipsruby/match.h +142 -0
- data/ext/clipsruby/memalloc.c +481 -0
- data/ext/clipsruby/memalloc.h +197 -0
- data/ext/clipsruby/miscfun.c +1801 -0
- data/ext/clipsruby/miscfun.h +132 -0
- data/ext/clipsruby/modulbin.c +607 -0
- data/ext/clipsruby/modulbin.h +84 -0
- data/ext/clipsruby/modulbsc.c +347 -0
- data/ext/clipsruby/modulbsc.h +67 -0
- data/ext/clipsruby/modulcmp.c +499 -0
- data/ext/clipsruby/modulcmp.h +54 -0
- data/ext/clipsruby/moduldef.c +817 -0
- data/ext/clipsruby/moduldef.h +271 -0
- data/ext/clipsruby/modulpsr.c +1150 -0
- data/ext/clipsruby/modulpsr.h +69 -0
- data/ext/clipsruby/modulutl.c +1036 -0
- data/ext/clipsruby/modulutl.h +84 -0
- data/ext/clipsruby/msgcom.c +1221 -0
- data/ext/clipsruby/msgcom.h +125 -0
- data/ext/clipsruby/msgfun.c +1076 -0
- data/ext/clipsruby/msgfun.h +118 -0
- data/ext/clipsruby/msgpass.c +1441 -0
- data/ext/clipsruby/msgpass.h +103 -0
- data/ext/clipsruby/msgpsr.c +698 -0
- data/ext/clipsruby/msgpsr.h +73 -0
- data/ext/clipsruby/multifld.c +1404 -0
- data/ext/clipsruby/multifld.h +130 -0
- data/ext/clipsruby/multifun.c +2182 -0
- data/ext/clipsruby/multifun.h +102 -0
- data/ext/clipsruby/network.h +142 -0
- data/ext/clipsruby/objbin.c +1522 -0
- data/ext/clipsruby/objbin.h +79 -0
- data/ext/clipsruby/objcmp.c +1507 -0
- data/ext/clipsruby/objcmp.h +71 -0
- data/ext/clipsruby/object.h +260 -0
- data/ext/clipsruby/objrtbin.c +701 -0
- data/ext/clipsruby/objrtbin.h +79 -0
- data/ext/clipsruby/objrtbld.c +2393 -0
- data/ext/clipsruby/objrtbld.h +66 -0
- data/ext/clipsruby/objrtcmp.c +734 -0
- data/ext/clipsruby/objrtcmp.h +66 -0
- data/ext/clipsruby/objrtfnx.c +1330 -0
- data/ext/clipsruby/objrtfnx.h +222 -0
- data/ext/clipsruby/objrtgen.c +736 -0
- data/ext/clipsruby/objrtgen.h +63 -0
- data/ext/clipsruby/objrtmch.c +1524 -0
- data/ext/clipsruby/objrtmch.h +160 -0
- data/ext/clipsruby/parsefun.c +415 -0
- data/ext/clipsruby/parsefun.h +67 -0
- data/ext/clipsruby/pattern.c +1265 -0
- data/ext/clipsruby/pattern.h +163 -0
- data/ext/clipsruby/pprint.c +328 -0
- data/ext/clipsruby/pprint.h +79 -0
- data/ext/clipsruby/prccode.c +1478 -0
- data/ext/clipsruby/prccode.h +145 -0
- data/ext/clipsruby/prcdrfun.c +640 -0
- data/ext/clipsruby/prcdrfun.h +95 -0
- data/ext/clipsruby/prcdrpsr.c +1068 -0
- data/ext/clipsruby/prcdrpsr.h +79 -0
- data/ext/clipsruby/prdctfun.c +869 -0
- data/ext/clipsruby/prdctfun.h +77 -0
- data/ext/clipsruby/prntutil.c +878 -0
- data/ext/clipsruby/prntutil.h +125 -0
- data/ext/clipsruby/proflfun.c +827 -0
- data/ext/clipsruby/proflfun.h +118 -0
- data/ext/clipsruby/reorder.c +2082 -0
- data/ext/clipsruby/reorder.h +172 -0
- data/ext/clipsruby/reteutil.c +1732 -0
- data/ext/clipsruby/reteutil.h +111 -0
- data/ext/clipsruby/retract.c +710 -0
- data/ext/clipsruby/retract.h +74 -0
- data/ext/clipsruby/router.c +737 -0
- data/ext/clipsruby/router.h +147 -0
- data/ext/clipsruby/rulebin.c +1136 -0
- data/ext/clipsruby/rulebin.h +153 -0
- data/ext/clipsruby/rulebld.c +1328 -0
- data/ext/clipsruby/rulebld.h +62 -0
- data/ext/clipsruby/rulebsc.c +517 -0
- data/ext/clipsruby/rulebsc.h +91 -0
- data/ext/clipsruby/rulecmp.c +733 -0
- data/ext/clipsruby/rulecmp.h +63 -0
- data/ext/clipsruby/rulecom.c +1583 -0
- data/ext/clipsruby/rulecom.h +116 -0
- data/ext/clipsruby/rulecstr.c +892 -0
- data/ext/clipsruby/rulecstr.h +53 -0
- data/ext/clipsruby/ruledef.c +559 -0
- data/ext/clipsruby/ruledef.h +179 -0
- data/ext/clipsruby/ruledlt.c +599 -0
- data/ext/clipsruby/ruledlt.h +58 -0
- data/ext/clipsruby/rulelhs.c +1216 -0
- data/ext/clipsruby/rulelhs.h +52 -0
- data/ext/clipsruby/rulepsr.c +1073 -0
- data/ext/clipsruby/rulepsr.h +61 -0
- data/ext/clipsruby/scanner.c +856 -0
- data/ext/clipsruby/scanner.h +112 -0
- data/ext/clipsruby/setup.h +488 -0
- data/ext/clipsruby/sortfun.c +433 -0
- data/ext/clipsruby/sortfun.h +55 -0
- data/ext/clipsruby/strngfun.c +1173 -0
- data/ext/clipsruby/strngfun.h +96 -0
- data/ext/clipsruby/strngrtr.c +523 -0
- data/ext/clipsruby/strngrtr.h +97 -0
- data/ext/clipsruby/symblbin.c +648 -0
- data/ext/clipsruby/symblbin.h +64 -0
- data/ext/clipsruby/symblcmp.c +893 -0
- data/ext/clipsruby/symblcmp.h +61 -0
- data/ext/clipsruby/symbol.c +1961 -0
- data/ext/clipsruby/symbol.h +243 -0
- data/ext/clipsruby/sysdep.c +894 -0
- data/ext/clipsruby/sysdep.h +164 -0
- data/ext/clipsruby/textpro.c +1388 -0
- data/ext/clipsruby/textpro.h +77 -0
- data/ext/clipsruby/tmpltbin.c +609 -0
- data/ext/clipsruby/tmpltbin.h +108 -0
- data/ext/clipsruby/tmpltbsc.c +327 -0
- data/ext/clipsruby/tmpltbsc.h +87 -0
- data/ext/clipsruby/tmpltcmp.c +450 -0
- data/ext/clipsruby/tmpltcmp.h +57 -0
- data/ext/clipsruby/tmpltdef.c +584 -0
- data/ext/clipsruby/tmpltdef.h +155 -0
- data/ext/clipsruby/tmpltfun.c +2477 -0
- data/ext/clipsruby/tmpltfun.h +122 -0
- data/ext/clipsruby/tmpltlhs.c +379 -0
- data/ext/clipsruby/tmpltlhs.h +50 -0
- data/ext/clipsruby/tmpltpsr.c +819 -0
- data/ext/clipsruby/tmpltpsr.h +59 -0
- data/ext/clipsruby/tmpltrhs.c +595 -0
- data/ext/clipsruby/tmpltrhs.h +55 -0
- data/ext/clipsruby/tmpltutl.c +637 -0
- data/ext/clipsruby/tmpltutl.h +82 -0
- data/ext/clipsruby/userdata.c +156 -0
- data/ext/clipsruby/userdata.h +72 -0
- data/ext/clipsruby/userfunctions.c +70 -0
- data/ext/clipsruby/usrsetup.h +7 -0
- data/ext/clipsruby/utility.c +1594 -0
- data/ext/clipsruby/utility.h +250 -0
- data/ext/clipsruby/watch.c +865 -0
- data/ext/clipsruby/watch.h +124 -0
- data/lib/clipsruby.rb +1 -0
- metadata +388 -0
@@ -0,0 +1,1328 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.40 06/28/17 */
|
5
|
+
/* */
|
6
|
+
/* RULE BUILD MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: Provides routines to ntegrates a set of pattern */
|
11
|
+
/* and join tests associated with a rule into the pattern */
|
12
|
+
/* and join networks. The joins are integrated into the */
|
13
|
+
/* join network by routines in this module. The pattern */
|
14
|
+
/* is integrated by calling the external routine */
|
15
|
+
/* associated with the pattern parser that originally */
|
16
|
+
/* parsed the pattern. */
|
17
|
+
/* */
|
18
|
+
/* Principal Programmer(s): */
|
19
|
+
/* Gary D. Riley */
|
20
|
+
/* */
|
21
|
+
/* Contributing Programmer(s): */
|
22
|
+
/* */
|
23
|
+
/* Revision History: */
|
24
|
+
/* */
|
25
|
+
/* 6.24: Removed INCREMENTAL_RESET compilation flag. */
|
26
|
+
/* */
|
27
|
+
/* Corrected code to remove compiler warnings. */
|
28
|
+
/* */
|
29
|
+
/* 6.30: Changes to constructing join network. */
|
30
|
+
/* */
|
31
|
+
/* Added support for hashed memories. */
|
32
|
+
/* */
|
33
|
+
/* 6.31: Fix for nand crash */
|
34
|
+
/* */
|
35
|
+
/* DR#882 Logical retraction not working if */
|
36
|
+
/* logical CE starts with test CE. */
|
37
|
+
/* */
|
38
|
+
/* 6.40: Pragma once and other inclusion changes. */
|
39
|
+
/* */
|
40
|
+
/* Added support for booleans with <stdbool.h>. */
|
41
|
+
/* */
|
42
|
+
/* Removed use of void pointers for specific */
|
43
|
+
/* data structures. */
|
44
|
+
/* */
|
45
|
+
/* Incremental reset is always enabled. */
|
46
|
+
/* */
|
47
|
+
/*************************************************************/
|
48
|
+
|
49
|
+
#include "setup.h"
|
50
|
+
|
51
|
+
#if DEFRULE_CONSTRUCT && (! RUN_TIME) && (! BLOAD_ONLY)
|
52
|
+
|
53
|
+
#include <stdio.h>
|
54
|
+
#include <stdlib.h>
|
55
|
+
|
56
|
+
#include "constant.h"
|
57
|
+
#include "envrnmnt.h"
|
58
|
+
#include "constrct.h"
|
59
|
+
#include "drive.h"
|
60
|
+
#include "incrrset.h"
|
61
|
+
#include "memalloc.h"
|
62
|
+
#include "pattern.h"
|
63
|
+
#include "prntutil.h"
|
64
|
+
#include "reteutil.h"
|
65
|
+
#include "router.h"
|
66
|
+
#include "rulebld.h"
|
67
|
+
#include "rulepsr.h"
|
68
|
+
#include "watch.h"
|
69
|
+
|
70
|
+
/***************************************/
|
71
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
72
|
+
/***************************************/
|
73
|
+
|
74
|
+
static struct joinNode *FindShareableJoin(struct joinLink *,struct joinNode *,bool,void *,bool,bool,
|
75
|
+
bool,bool,struct expr *,struct expr *,
|
76
|
+
struct expr *,struct expr *);
|
77
|
+
static bool TestJoinForReuse(struct joinNode *,bool,bool,
|
78
|
+
bool,bool,struct expr *,struct expr *,
|
79
|
+
struct expr *,struct expr *);
|
80
|
+
static struct joinNode *CreateNewJoin(Environment *,struct expr *,struct expr *,struct joinNode *,void *,
|
81
|
+
bool,bool,bool,struct expr *,struct expr *);
|
82
|
+
|
83
|
+
/****************************************************************/
|
84
|
+
/* ConstructJoins: Integrates a set of pattern and join tests */
|
85
|
+
/* associated with a rule into the pattern and join networks. */
|
86
|
+
/****************************************************************/
|
87
|
+
struct joinNode *ConstructJoins(
|
88
|
+
Environment *theEnv,
|
89
|
+
int logicalJoin,
|
90
|
+
struct lhsParseNode *theLHS,
|
91
|
+
int startDepth,
|
92
|
+
struct joinNode *lastJoin,
|
93
|
+
bool tryToReuse,
|
94
|
+
bool firstJoin)
|
95
|
+
{
|
96
|
+
struct patternNodeHeader *lastPattern;
|
97
|
+
struct joinNode *listOfJoins = NULL;
|
98
|
+
struct joinNode *oldJoin;
|
99
|
+
int joinNumber = 1;
|
100
|
+
bool isLogical, isExists;
|
101
|
+
struct joinNode *lastRightJoin;
|
102
|
+
bool lastIteration = false;
|
103
|
+
unsigned short rhsType;
|
104
|
+
struct expr *leftHash, *rightHash;
|
105
|
+
void *rhsStruct;
|
106
|
+
struct lhsParseNode *nextLHS;
|
107
|
+
struct expr *networkTest, *secondaryNetworkTest, *secondaryExternalTest;
|
108
|
+
bool joinFromTheRight;
|
109
|
+
struct joinLink *theLinks;
|
110
|
+
bool useLinks;
|
111
|
+
|
112
|
+
if (theLHS == NULL)
|
113
|
+
{
|
114
|
+
lastJoin = FindShareableJoin(DefruleData(theEnv)->RightPrimeJoins,NULL,true,NULL,true,
|
115
|
+
false,false,false,NULL,NULL,NULL,NULL);
|
116
|
+
|
117
|
+
if (lastJoin == NULL)
|
118
|
+
{ lastJoin = CreateNewJoin(theEnv,NULL,NULL,NULL,NULL,false,false,false,NULL,NULL); }
|
119
|
+
}
|
120
|
+
|
121
|
+
/*=====================================================*/
|
122
|
+
/* Process each pattern CE in the rule. At this point, */
|
123
|
+
/* there should be no and/or/not CEs in the LHS. */
|
124
|
+
/*=====================================================*/
|
125
|
+
|
126
|
+
while (theLHS != NULL)
|
127
|
+
{
|
128
|
+
/*======================================================*/
|
129
|
+
/* Find the beginning of the next group of patterns. If */
|
130
|
+
/* the current pattern is not the beginning of a "join */
|
131
|
+
/* from the right" group of patterns, then the next */
|
132
|
+
/* pattern is the next pattern. Otherwise skip over all */
|
133
|
+
/* the patterns that belong to the group of subjoins. */
|
134
|
+
/*======================================================*/
|
135
|
+
|
136
|
+
nextLHS = theLHS->bottom;
|
137
|
+
secondaryExternalTest = NULL;
|
138
|
+
|
139
|
+
if (theLHS->endNandDepth > startDepth)
|
140
|
+
{
|
141
|
+
while ((nextLHS != NULL) &&
|
142
|
+
(nextLHS->endNandDepth > startDepth))
|
143
|
+
{ nextLHS = nextLHS->bottom; }
|
144
|
+
|
145
|
+
/*====================================================*/
|
146
|
+
/* Variable nextLHS is now pointing to the end of the */
|
147
|
+
/* not/and group beginning with variable theLHS. If */
|
148
|
+
/* the end depth of the group is less than the depth */
|
149
|
+
/* of the current enclosing not/and group, then this */
|
150
|
+
/* is the last iteration for the enclosing group. */
|
151
|
+
/*====================================================*/
|
152
|
+
|
153
|
+
if (nextLHS != NULL)
|
154
|
+
{
|
155
|
+
if (nextLHS->endNandDepth < startDepth)
|
156
|
+
{ lastIteration = true; }
|
157
|
+
}
|
158
|
+
|
159
|
+
if (! lastIteration)
|
160
|
+
{
|
161
|
+
if (nextLHS != NULL)
|
162
|
+
{ nextLHS = nextLHS->bottom; }
|
163
|
+
|
164
|
+
if ((nextLHS != NULL) &&
|
165
|
+
(nextLHS->pnType == TEST_CE_NODE) &&
|
166
|
+
(nextLHS->beginNandDepth >= startDepth))
|
167
|
+
{
|
168
|
+
if (nextLHS->endNandDepth < startDepth)
|
169
|
+
{ lastIteration = true; }
|
170
|
+
|
171
|
+
secondaryExternalTest = nextLHS->networkTest;
|
172
|
+
nextLHS = nextLHS->bottom;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
else if (theLHS->endNandDepth == startDepth)
|
177
|
+
{
|
178
|
+
if (nextLHS == NULL)
|
179
|
+
{ lastIteration = true; }
|
180
|
+
else if ((nextLHS->pnType == TEST_CE_NODE) &&
|
181
|
+
(nextLHS->endNandDepth < startDepth))
|
182
|
+
{ lastIteration = true; }
|
183
|
+
}
|
184
|
+
else // theLHS->endNandDepth < startDepth
|
185
|
+
{
|
186
|
+
lastIteration = true;
|
187
|
+
}
|
188
|
+
|
189
|
+
/*===============================================*/
|
190
|
+
/* If the pattern is a join from the right, then */
|
191
|
+
/* construct the subgroup of patterns and use */
|
192
|
+
/* that as the RHS of the join to be added. */
|
193
|
+
/*===============================================*/
|
194
|
+
|
195
|
+
if (theLHS->beginNandDepth > startDepth)
|
196
|
+
{
|
197
|
+
joinFromTheRight = true;
|
198
|
+
isExists = theLHS->existsNand;
|
199
|
+
|
200
|
+
lastRightJoin = ConstructJoins(theEnv,logicalJoin,theLHS,startDepth+1,lastJoin,tryToReuse,firstJoin);
|
201
|
+
|
202
|
+
rhsStruct = lastRightJoin;
|
203
|
+
rhsType = 0;
|
204
|
+
lastPattern = NULL;
|
205
|
+
networkTest = theLHS->externalNetworkTest;
|
206
|
+
secondaryNetworkTest = secondaryExternalTest;
|
207
|
+
leftHash = theLHS->externalLeftHash;
|
208
|
+
rightHash = theLHS->externalRightHash;
|
209
|
+
}
|
210
|
+
|
211
|
+
/*=======================================================*/
|
212
|
+
/* Otherwise, add the pattern to the appropriate pattern */
|
213
|
+
/* network and use the pattern node containing the alpha */
|
214
|
+
/* memory as the RHS of the join to be added. */
|
215
|
+
/*=======================================================*/
|
216
|
+
|
217
|
+
else if (theLHS->right == NULL)
|
218
|
+
{
|
219
|
+
joinFromTheRight = false;
|
220
|
+
rhsType = 0;
|
221
|
+
lastPattern = NULL;
|
222
|
+
rhsStruct = NULL;
|
223
|
+
lastRightJoin = NULL;
|
224
|
+
isExists = theLHS->exists;
|
225
|
+
networkTest = theLHS->networkTest;
|
226
|
+
secondaryNetworkTest = theLHS->secondaryNetworkTest;
|
227
|
+
leftHash = NULL;
|
228
|
+
rightHash = NULL;
|
229
|
+
}
|
230
|
+
else
|
231
|
+
{
|
232
|
+
joinFromTheRight = false;
|
233
|
+
rhsType = theLHS->patternType->positionInArray;
|
234
|
+
lastPattern = (*theLHS->patternType->addPatternFunction)(theEnv,theLHS);
|
235
|
+
rhsStruct = lastPattern;
|
236
|
+
lastRightJoin = NULL;
|
237
|
+
isExists = theLHS->exists;
|
238
|
+
networkTest = theLHS->networkTest;
|
239
|
+
secondaryNetworkTest = theLHS->secondaryNetworkTest;
|
240
|
+
leftHash = theLHS->leftHash;
|
241
|
+
rightHash = theLHS->rightHash;
|
242
|
+
}
|
243
|
+
|
244
|
+
/*======================================================*/
|
245
|
+
/* Determine if the join being added is a logical join. */
|
246
|
+
/*======================================================*/
|
247
|
+
|
248
|
+
if ((startDepth == 1) && (joinNumber == logicalJoin)) isLogical = true;
|
249
|
+
else isLogical = false;
|
250
|
+
|
251
|
+
/*===============================================*/
|
252
|
+
/* Get the list of joins which could potentially */
|
253
|
+
/* be reused in place of the join being added. */
|
254
|
+
/*===============================================*/
|
255
|
+
|
256
|
+
useLinks = true;
|
257
|
+
if (lastJoin != NULL)
|
258
|
+
{ theLinks = lastJoin->nextLinks; }
|
259
|
+
else if (theLHS->right == NULL)
|
260
|
+
{ theLinks = DefruleData(theEnv)->RightPrimeJoins; }
|
261
|
+
else if (lastPattern != NULL)
|
262
|
+
{
|
263
|
+
listOfJoins = lastPattern->entryJoin;
|
264
|
+
theLinks = NULL;
|
265
|
+
useLinks = false;
|
266
|
+
}
|
267
|
+
else
|
268
|
+
{ theLinks = lastRightJoin->nextLinks; }
|
269
|
+
|
270
|
+
/*=======================================================*/
|
271
|
+
/* Determine if the next join to be added can be shared. */
|
272
|
+
/*=======================================================*/
|
273
|
+
|
274
|
+
if ((tryToReuse == true) &&
|
275
|
+
((oldJoin = FindShareableJoin(theLinks,listOfJoins,useLinks,rhsStruct,firstJoin,
|
276
|
+
theLHS->negated,isExists,isLogical,
|
277
|
+
networkTest,secondaryNetworkTest,
|
278
|
+
leftHash,rightHash)) != NULL) )
|
279
|
+
{
|
280
|
+
#if DEBUGGING_FUNCTIONS
|
281
|
+
if ((GetWatchItem(theEnv,"compilations") == 1) && GetPrintWhileLoading(theEnv))
|
282
|
+
{ WriteString(theEnv,STDOUT,"=j"); }
|
283
|
+
#endif
|
284
|
+
lastJoin = oldJoin;
|
285
|
+
}
|
286
|
+
else
|
287
|
+
{
|
288
|
+
tryToReuse = false;
|
289
|
+
if (! joinFromTheRight)
|
290
|
+
{
|
291
|
+
lastJoin = CreateNewJoin(theEnv,networkTest,secondaryNetworkTest,lastJoin,
|
292
|
+
lastPattern,false,theLHS->negated, isExists,
|
293
|
+
leftHash,rightHash);
|
294
|
+
lastJoin->rhsType = rhsType;
|
295
|
+
}
|
296
|
+
else
|
297
|
+
{
|
298
|
+
lastJoin = CreateNewJoin(theEnv,networkTest,secondaryNetworkTest,lastJoin,
|
299
|
+
lastRightJoin,true,theLHS->negated, isExists,
|
300
|
+
leftHash,rightHash);
|
301
|
+
lastJoin->rhsType = rhsType;
|
302
|
+
}
|
303
|
+
}
|
304
|
+
|
305
|
+
/*============================================*/
|
306
|
+
/* If we've reached the end of the subgroup, */
|
307
|
+
/* then return the last join of the subgroup. */
|
308
|
+
/*============================================*/
|
309
|
+
|
310
|
+
if (lastIteration)
|
311
|
+
{ break; }
|
312
|
+
|
313
|
+
/*=======================================*/
|
314
|
+
/* Move on to the next join to be added. */
|
315
|
+
/*=======================================*/
|
316
|
+
|
317
|
+
theLHS = nextLHS;
|
318
|
+
joinNumber++;
|
319
|
+
firstJoin = false;
|
320
|
+
}
|
321
|
+
|
322
|
+
/*=================================================*/
|
323
|
+
/* Add the final join which stores the activations */
|
324
|
+
/* of the rule. This join is never shared. */
|
325
|
+
/*=================================================*/
|
326
|
+
|
327
|
+
if (startDepth == 1)
|
328
|
+
{
|
329
|
+
lastJoin = CreateNewJoin(theEnv,NULL,NULL,lastJoin,NULL,
|
330
|
+
false,false,false,NULL,NULL);
|
331
|
+
}
|
332
|
+
|
333
|
+
/*===================================================*/
|
334
|
+
/* If compilations are being watched, put a carriage */
|
335
|
+
/* return after all of the =j's and +j's */
|
336
|
+
/*===================================================*/
|
337
|
+
|
338
|
+
#if DEBUGGING_FUNCTIONS
|
339
|
+
if ((startDepth == 1) &&
|
340
|
+
(GetWatchItem(theEnv,"compilations") == 1) &&
|
341
|
+
GetPrintWhileLoading(theEnv))
|
342
|
+
{ WriteString(theEnv,STDOUT,"\n"); }
|
343
|
+
#endif
|
344
|
+
|
345
|
+
/*=============================*/
|
346
|
+
/* Return the last join added. */
|
347
|
+
/*=============================*/
|
348
|
+
|
349
|
+
return(lastJoin);
|
350
|
+
}
|
351
|
+
|
352
|
+
/****************************************************************/
|
353
|
+
/* AttachTestCEsToPatternCEs: Attaches the expressions found in */
|
354
|
+
/* test CEs to the closest preceeding pattern CE that is not */
|
355
|
+
/* negated and is at the same not/and depth. */
|
356
|
+
/****************************************************************/
|
357
|
+
void AttachTestCEsToPatternCEs(
|
358
|
+
Environment *theEnv,
|
359
|
+
struct lhsParseNode *theLHS)
|
360
|
+
{
|
361
|
+
struct lhsParseNode *lastNode, *tempNode, *lastLastNode;
|
362
|
+
|
363
|
+
if (theLHS == NULL) return;
|
364
|
+
|
365
|
+
/*=============================================================*/
|
366
|
+
/* Attach test CEs that can be attached directly to a pattern. */
|
367
|
+
/*=============================================================*/
|
368
|
+
|
369
|
+
lastLastNode = NULL;
|
370
|
+
lastNode = theLHS;
|
371
|
+
theLHS = lastNode->bottom;
|
372
|
+
|
373
|
+
while (theLHS != NULL)
|
374
|
+
{
|
375
|
+
/*================================================================*/
|
376
|
+
/* Skip over any CE that's not a TEST CE as we're only interested */
|
377
|
+
/* in attaching a TEST CE to a preceding pattern CE. Update the */
|
378
|
+
/* variables that track the preceding pattern. */
|
379
|
+
/*================================================================*/
|
380
|
+
|
381
|
+
if (theLHS->pnType != TEST_CE_NODE)
|
382
|
+
{
|
383
|
+
lastLastNode = lastNode;
|
384
|
+
lastNode = theLHS;
|
385
|
+
theLHS = theLHS->bottom;
|
386
|
+
continue;
|
387
|
+
}
|
388
|
+
|
389
|
+
/*=====================================================*/
|
390
|
+
/* If this is the beginning of a new NOT/AND CE group, */
|
391
|
+
/* then we can't attach this TEST CE to a preceding */
|
392
|
+
/* pattern CE and should skip over it. */
|
393
|
+
/*=====================================================*/
|
394
|
+
|
395
|
+
/*================================================*/
|
396
|
+
/* Case #2 */
|
397
|
+
/* Pattern CE */
|
398
|
+
/* Depth Begin: N */
|
399
|
+
/* Depth End: N */
|
400
|
+
/* Test CE */
|
401
|
+
/* Depth Begin: M where M > N */
|
402
|
+
/* Depth End: - */
|
403
|
+
/* */
|
404
|
+
/* (defrule example */
|
405
|
+
/* (a) */
|
406
|
+
/* (not (and (test (> 1 0)) */
|
407
|
+
/* (b))) */
|
408
|
+
/* =>) */
|
409
|
+
/* */
|
410
|
+
/* Case #8 */
|
411
|
+
/* Pattern CE */
|
412
|
+
/* Depth Begin: N */
|
413
|
+
/* Depth End: M where M < N */
|
414
|
+
/* Test CE */
|
415
|
+
/* Depth Begin: R where R > M */
|
416
|
+
/* Depth End: - */
|
417
|
+
/* */
|
418
|
+
/* (defrule example */
|
419
|
+
/* (not (and (a) */
|
420
|
+
/* (c))) */
|
421
|
+
/* (not (and (test (> 1 0)) */
|
422
|
+
/* (b))) */
|
423
|
+
/* =>) */
|
424
|
+
/* */
|
425
|
+
/* This situation will not occur with the current */
|
426
|
+
/* implementation. The initial pattern will be */
|
427
|
+
/* added before the test CE so that there is a */
|
428
|
+
/* pattern CE beginning the not/and or exists/and */
|
429
|
+
/* pattern group. */
|
430
|
+
/*================================================*/
|
431
|
+
|
432
|
+
if (theLHS->beginNandDepth > lastNode->endNandDepth)
|
433
|
+
{
|
434
|
+
lastLastNode = lastNode;
|
435
|
+
lastNode = theLHS;
|
436
|
+
theLHS = theLHS->bottom;
|
437
|
+
continue;
|
438
|
+
}
|
439
|
+
|
440
|
+
/*==============================================================*/
|
441
|
+
/* If the preceding pattern was the end of a NOT/AND CE group, */
|
442
|
+
/* then we can't attach this TEST CE to a preceding pattern and */
|
443
|
+
/* should skip over it. The logic for handling the test CE will */
|
444
|
+
/* be triggered when the joins are constructed. Note that the */
|
445
|
+
/* endNandDepth will never be greater than the beginNandDepth. */
|
446
|
+
/*==============================================================*/
|
447
|
+
|
448
|
+
if (lastNode->beginNandDepth > lastNode->endNandDepth)
|
449
|
+
{
|
450
|
+
lastLastNode = lastNode;
|
451
|
+
lastNode = theLHS;
|
452
|
+
theLHS = theLHS->bottom;
|
453
|
+
continue;
|
454
|
+
}
|
455
|
+
|
456
|
+
/*===================================================*/
|
457
|
+
/* If the TEST CE does not close the preceding CE... */
|
458
|
+
/*===================================================*/
|
459
|
+
|
460
|
+
/*===================================================*/
|
461
|
+
/* Case #1 */
|
462
|
+
/* Pattern CE */
|
463
|
+
/* Depth Begin: N */
|
464
|
+
/* Depth End: N */
|
465
|
+
/* Test CE */
|
466
|
+
/* Depth Begin: N */
|
467
|
+
/* Depth End: N */
|
468
|
+
/* */
|
469
|
+
/* (defrule example */
|
470
|
+
/* (a ?x) */
|
471
|
+
/* (test (> ?x 0)) */
|
472
|
+
/* =>) */
|
473
|
+
/* */
|
474
|
+
/* The test expression can be directly attached to */
|
475
|
+
/* the network expression for the preceding pattern. */
|
476
|
+
/*===================================================*/
|
477
|
+
|
478
|
+
if (theLHS->beginNandDepth == theLHS->endNandDepth)
|
479
|
+
{
|
480
|
+
/*==============================================================*/
|
481
|
+
/* If the preceding pattern was a NOT or EXISTS CE containing */
|
482
|
+
/* a single pattern, then attached the TEST CE to the secondary */
|
483
|
+
/* test, otherwise combine it with the primary network test. */
|
484
|
+
/*==============================================================*/
|
485
|
+
|
486
|
+
if (lastNode->negated)
|
487
|
+
{
|
488
|
+
lastNode->secondaryNetworkTest =
|
489
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
490
|
+
}
|
491
|
+
else
|
492
|
+
{
|
493
|
+
lastNode->networkTest =
|
494
|
+
CombineExpressions(theEnv,lastNode->networkTest,theLHS->networkTest);
|
495
|
+
}
|
496
|
+
}
|
497
|
+
|
498
|
+
/*=================================================================*/
|
499
|
+
/* Otherwise the TEST CE closes a prior NOT/AND or EXISTS/AND CE. */
|
500
|
+
/*=================================================================*/
|
501
|
+
|
502
|
+
/*==================================================*/
|
503
|
+
/* If these are the first two patterns in the rule. */
|
504
|
+
/*==================================================*/
|
505
|
+
|
506
|
+
/*=========*/
|
507
|
+
/* Case #3 */
|
508
|
+
/*=========*/
|
509
|
+
|
510
|
+
else if (lastLastNode == NULL)
|
511
|
+
{
|
512
|
+
/*=========================================================*/
|
513
|
+
/* The prior pattern is a single pattern within a not/and. */
|
514
|
+
/* */
|
515
|
+
/* (defrule example */
|
516
|
+
/* (not (and (b) */
|
517
|
+
/* (test (= 1 1)))) */
|
518
|
+
/* =>) */
|
519
|
+
/* */
|
520
|
+
/* Collapse the nand pattern. */
|
521
|
+
/*=========================================================*/
|
522
|
+
|
523
|
+
if ((lastNode->negated == false) &&
|
524
|
+
(lastNode->existsNand == false))
|
525
|
+
{
|
526
|
+
lastNode->beginNandDepth = theLHS->endNandDepth;
|
527
|
+
|
528
|
+
lastNode->negated = true;
|
529
|
+
|
530
|
+
lastNode->networkTest =
|
531
|
+
CombineExpressions(theEnv,lastNode->networkTest,lastNode->externalNetworkTest);
|
532
|
+
lastNode->networkTest =
|
533
|
+
CombineExpressions(theEnv,lastNode->networkTest,theLHS->networkTest);
|
534
|
+
lastNode->externalNetworkTest = NULL;
|
535
|
+
}
|
536
|
+
|
537
|
+
/*=================================================================*/
|
538
|
+
/* The prior pattern is a single negated pattern within a not/and. */
|
539
|
+
/* */
|
540
|
+
/* (defrule example */
|
541
|
+
/* (not (and (not (b)) */
|
542
|
+
/* (test (= 1 1)))) */
|
543
|
+
/* =>) */
|
544
|
+
/* */
|
545
|
+
/*=================================================================*/
|
546
|
+
|
547
|
+
else if ((lastNode->negated == true) &&
|
548
|
+
(lastNode->exists == false) &&
|
549
|
+
(lastNode->existsNand == false))
|
550
|
+
{
|
551
|
+
lastNode->secondaryNetworkTest =
|
552
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
553
|
+
}
|
554
|
+
|
555
|
+
/*================================================================*/
|
556
|
+
/* The prior pattern is a single exists pattern within a not/and. */
|
557
|
+
/* */
|
558
|
+
/* (defrule example */
|
559
|
+
/* (not (and (exists (b)) */
|
560
|
+
/* (test (= 1 1)))) */
|
561
|
+
/* =>) */
|
562
|
+
/* */
|
563
|
+
/*================================================================*/
|
564
|
+
|
565
|
+
else if ((lastNode->negated == true) &&
|
566
|
+
(lastNode->exists == true) &&
|
567
|
+
(lastNode->existsNand == false))
|
568
|
+
{
|
569
|
+
lastNode->secondaryNetworkTest =
|
570
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
571
|
+
}
|
572
|
+
|
573
|
+
/*=============================================================*/
|
574
|
+
/* The prior pattern is a single pattern within an exists/and. */
|
575
|
+
/* */
|
576
|
+
/* (defrule example */
|
577
|
+
/* (exists (and (b) */
|
578
|
+
/* (test (= 1 1)))) */
|
579
|
+
/* =>) */
|
580
|
+
/* */
|
581
|
+
/* Collapse the exists pattern. */
|
582
|
+
/*=============================================================*/
|
583
|
+
|
584
|
+
else if ((lastNode->negated == false) &&
|
585
|
+
(lastNode->exists == false) &&
|
586
|
+
(lastNode->existsNand == true))
|
587
|
+
{
|
588
|
+
lastNode->beginNandDepth = theLHS->endNandDepth;
|
589
|
+
|
590
|
+
lastNode->existsNand = false;
|
591
|
+
lastNode->exists = true;
|
592
|
+
lastNode->negated = true;
|
593
|
+
|
594
|
+
/*===================================================*/
|
595
|
+
/* For the first two patterns, there shouldn't be an */
|
596
|
+
/* externalNetwork test, but this code is included */
|
597
|
+
/* to match the other cases where patterns are */
|
598
|
+
/* collapsed. */
|
599
|
+
/*===================================================*/
|
600
|
+
|
601
|
+
lastNode->networkTest =
|
602
|
+
CombineExpressions(theEnv,lastNode->networkTest,lastNode->externalNetworkTest);
|
603
|
+
lastNode->networkTest =
|
604
|
+
CombineExpressions(theEnv,lastNode->networkTest,theLHS->networkTest);
|
605
|
+
lastNode->externalNetworkTest = NULL;
|
606
|
+
}
|
607
|
+
|
608
|
+
/*=======================================*/
|
609
|
+
/* The prior pattern is a single negated */
|
610
|
+
/* pattern within an exists/and. */
|
611
|
+
/* */
|
612
|
+
/* (defrule example */
|
613
|
+
/* (exists (and (not (b)) */
|
614
|
+
/* (test (= 1 1)))) */
|
615
|
+
/* =>) */
|
616
|
+
/* */
|
617
|
+
/*=======================================*/
|
618
|
+
|
619
|
+
else if ((lastNode->negated == true) &&
|
620
|
+
(lastNode->exists == false) &&
|
621
|
+
(lastNode->existsNand == true))
|
622
|
+
{
|
623
|
+
lastNode->secondaryNetworkTest =
|
624
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
625
|
+
}
|
626
|
+
|
627
|
+
/*======================================*/
|
628
|
+
/* The prior pattern is a single exists */
|
629
|
+
/* pattern within an exists/and. */
|
630
|
+
/* */
|
631
|
+
/* (defrule example */
|
632
|
+
/* (exists (and (exists (b)) */
|
633
|
+
/* (test (= 1 1)))) */
|
634
|
+
/* =>) */
|
635
|
+
/* */
|
636
|
+
/* Collapse the exists pattern. */
|
637
|
+
/*======================================*/
|
638
|
+
|
639
|
+
else if ((lastNode->negated == true) &&
|
640
|
+
(lastNode->exists == true) &&
|
641
|
+
(lastNode->existsNand == true))
|
642
|
+
{
|
643
|
+
lastNode->beginNandDepth = theLHS->endNandDepth;
|
644
|
+
|
645
|
+
lastNode->existsNand = false;
|
646
|
+
|
647
|
+
/*===================================================*/
|
648
|
+
/* For the first two patterns, there shouldn't be an */
|
649
|
+
/* externalNetwork test, but this code is included */
|
650
|
+
/* to match the other cases where patterns are */
|
651
|
+
/* collapsed. */
|
652
|
+
/*===================================================*/
|
653
|
+
|
654
|
+
lastNode->secondaryNetworkTest =
|
655
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,lastNode->externalNetworkTest);
|
656
|
+
lastNode->secondaryNetworkTest =
|
657
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
658
|
+
lastNode->externalNetworkTest = NULL;
|
659
|
+
}
|
660
|
+
|
661
|
+
/*==============================================*/
|
662
|
+
/* Unhandled case which should not be possible. */
|
663
|
+
/*==============================================*/
|
664
|
+
|
665
|
+
else
|
666
|
+
{
|
667
|
+
SystemError(theEnv,"RULEBLD",1);
|
668
|
+
ExitRouter(theEnv,EXIT_FAILURE);
|
669
|
+
}
|
670
|
+
}
|
671
|
+
|
672
|
+
/*==============================================*/
|
673
|
+
/* Otherwise, there are two preceding patterns. */
|
674
|
+
/*==============================================*/
|
675
|
+
|
676
|
+
/*====================================*/
|
677
|
+
/* Case #4 */
|
678
|
+
/* Pattern CE */
|
679
|
+
/* Depth Begin: - */
|
680
|
+
/* Depth End: N */
|
681
|
+
/* Pattern CE */
|
682
|
+
/* Depth Begin: N */
|
683
|
+
/* Depth End: N */
|
684
|
+
/* Test CE */
|
685
|
+
/* Depth Begin: N */
|
686
|
+
/* Depth End: M where M < N */
|
687
|
+
/*====================================*/
|
688
|
+
|
689
|
+
else if (lastLastNode->endNandDepth == theLHS->beginNandDepth)
|
690
|
+
{
|
691
|
+
/*==============================================================*/
|
692
|
+
/* If the preceding pattern was a NOT or EXISTS CE containing */
|
693
|
+
/* a single pattern, then attached the TEST CE to the secondary */
|
694
|
+
/* test, otherwise combine it with the primary network test. */
|
695
|
+
/*==============================================================*/
|
696
|
+
|
697
|
+
if (lastNode->negated)
|
698
|
+
{
|
699
|
+
lastNode->secondaryNetworkTest =
|
700
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
701
|
+
}
|
702
|
+
else
|
703
|
+
{
|
704
|
+
lastNode->networkTest =
|
705
|
+
CombineExpressions(theEnv,lastNode->networkTest,theLHS->networkTest);
|
706
|
+
}
|
707
|
+
}
|
708
|
+
|
709
|
+
/*====================================*/
|
710
|
+
/* Case #5 */
|
711
|
+
/* Pattern CE */
|
712
|
+
/* Depth Begin: - */
|
713
|
+
/* Depth End: R where R < N */
|
714
|
+
/* Pattern CE */
|
715
|
+
/* Depth Begin: N */
|
716
|
+
/* Depth End: N */
|
717
|
+
/* Test CE */
|
718
|
+
/* Depth Begin: N */
|
719
|
+
/* Depth End: M where M < N */
|
720
|
+
/*====================================*/
|
721
|
+
|
722
|
+
else if (lastLastNode->endNandDepth < theLHS->beginNandDepth)
|
723
|
+
{
|
724
|
+
/*=========================================================*/
|
725
|
+
/* The prior pattern is a single pattern within a not/and: */
|
726
|
+
/* */
|
727
|
+
/* (defrule example */
|
728
|
+
/* (a) */
|
729
|
+
/* (not (and (b) */
|
730
|
+
/* (test (= 1 1)))) */
|
731
|
+
/* =>) */
|
732
|
+
/* */
|
733
|
+
/* The test expression can be directly attached to the */
|
734
|
+
/* network expression for the pattern and the pattern */
|
735
|
+
/* group can be collapsed into a single negated pattern. */
|
736
|
+
/*=========================================================*/
|
737
|
+
|
738
|
+
if ((lastNode->negated == false) &&
|
739
|
+
(lastNode->existsNand == false))
|
740
|
+
{
|
741
|
+
/*====================*/
|
742
|
+
/* Use max of R and M */
|
743
|
+
/*====================*/
|
744
|
+
|
745
|
+
if (lastLastNode->endNandDepth > theLHS->endNandDepth)
|
746
|
+
{ lastNode->beginNandDepth = lastLastNode->endNandDepth; }
|
747
|
+
else
|
748
|
+
{ lastNode->beginNandDepth = theLHS->endNandDepth; }
|
749
|
+
|
750
|
+
lastNode->negated = true;
|
751
|
+
|
752
|
+
lastNode->networkTest =
|
753
|
+
CombineExpressions(theEnv,lastNode->networkTest,lastNode->externalNetworkTest);
|
754
|
+
lastNode->networkTest =
|
755
|
+
CombineExpressions(theEnv,lastNode->networkTest,theLHS->networkTest);
|
756
|
+
lastNode->externalNetworkTest = NULL;
|
757
|
+
}
|
758
|
+
|
759
|
+
/*=================================================================*/
|
760
|
+
/* The prior pattern is a single negated pattern within a not/and. */
|
761
|
+
/* */
|
762
|
+
/* (defrule example */
|
763
|
+
/* (a) */
|
764
|
+
/* (not (and (not (b)) */
|
765
|
+
/* (test (= 1 1)))) */
|
766
|
+
/* =>) */
|
767
|
+
/*=================================================================*/
|
768
|
+
|
769
|
+
else if ((lastNode->negated == true) &&
|
770
|
+
(lastNode->exists == false) &&
|
771
|
+
(lastNode->existsNand == false))
|
772
|
+
{
|
773
|
+
lastNode->secondaryNetworkTest =
|
774
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
775
|
+
}
|
776
|
+
|
777
|
+
/*================================================================*/
|
778
|
+
/* The prior pattern is a single exists pattern within a not/and. */
|
779
|
+
/* */
|
780
|
+
/* (defrule example */
|
781
|
+
/* (a) */
|
782
|
+
/* (not (and (exists (b)) */
|
783
|
+
/* (test (= 1 1)))) */
|
784
|
+
/* =>) */
|
785
|
+
/*================================================================*/
|
786
|
+
|
787
|
+
else if ((lastNode->negated == true) &&
|
788
|
+
(lastNode->exists == true) &&
|
789
|
+
(lastNode->existsNand == false))
|
790
|
+
{
|
791
|
+
lastNode->secondaryNetworkTest =
|
792
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
793
|
+
}
|
794
|
+
|
795
|
+
/*=============================================================*/
|
796
|
+
/* The prior pattern is a single pattern within an exists/and. */
|
797
|
+
/* */
|
798
|
+
/* (defrule example */
|
799
|
+
/* (a) */
|
800
|
+
/* (exists (and (b) */
|
801
|
+
/* (test (= 1 1)))) */
|
802
|
+
/* =>) */
|
803
|
+
/* */
|
804
|
+
/* The test expression can be directly attached to the */
|
805
|
+
/* network expression for the pattern and the pattern */
|
806
|
+
/* group can be collapsed into a single exists pattern. */
|
807
|
+
/*=============================================================*/
|
808
|
+
|
809
|
+
else if ((lastNode->negated == false) &&
|
810
|
+
(lastNode->exists == false) &&
|
811
|
+
(lastNode->existsNand == true))
|
812
|
+
{
|
813
|
+
if (lastLastNode->endNandDepth > theLHS->endNandDepth)
|
814
|
+
{ lastNode->beginNandDepth = lastLastNode->endNandDepth; }
|
815
|
+
else
|
816
|
+
{ lastNode->beginNandDepth = theLHS->endNandDepth; }
|
817
|
+
|
818
|
+
lastNode->existsNand = false;
|
819
|
+
lastNode->exists = true;
|
820
|
+
lastNode->negated = true;
|
821
|
+
|
822
|
+
lastNode->networkTest =
|
823
|
+
CombineExpressions(theEnv,lastNode->networkTest,lastNode->externalNetworkTest);
|
824
|
+
lastNode->networkTest =
|
825
|
+
CombineExpressions(theEnv,lastNode->networkTest,theLHS->networkTest);
|
826
|
+
lastNode->externalNetworkTest = NULL;
|
827
|
+
}
|
828
|
+
|
829
|
+
/*=======================================*/
|
830
|
+
/* The prior pattern is a single negated */
|
831
|
+
/* pattern within an exists/and. */
|
832
|
+
/* */
|
833
|
+
/* (defrule example */
|
834
|
+
/* (a) */
|
835
|
+
/* (exists (and (not (b)) */
|
836
|
+
/* (test (= 1 1)))) */
|
837
|
+
/* =>) */
|
838
|
+
/* */
|
839
|
+
/*=======================================*/
|
840
|
+
|
841
|
+
else if ((lastNode->negated == true) &&
|
842
|
+
(lastNode->exists == false) &&
|
843
|
+
(lastNode->existsNand == true))
|
844
|
+
{
|
845
|
+
lastNode->secondaryNetworkTest =
|
846
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
847
|
+
}
|
848
|
+
|
849
|
+
/*======================================*/
|
850
|
+
/* The prior pattern is a single exists */
|
851
|
+
/* pattern within an exists/and. */
|
852
|
+
/* */
|
853
|
+
/* (defrule example */
|
854
|
+
/* (a) */
|
855
|
+
/* (exists (and (exists (b)) */
|
856
|
+
/* (test (= 1 1)))) */
|
857
|
+
/* =>) */
|
858
|
+
/* */
|
859
|
+
/*======================================*/
|
860
|
+
|
861
|
+
else if ((lastNode->negated == true) &&
|
862
|
+
(lastNode->exists == true) &&
|
863
|
+
(lastNode->existsNand == true))
|
864
|
+
{
|
865
|
+
lastNode->secondaryNetworkTest =
|
866
|
+
CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
|
867
|
+
}
|
868
|
+
|
869
|
+
/*==============================================*/
|
870
|
+
/* Unhandled case which should not be possible. */
|
871
|
+
/*==============================================*/
|
872
|
+
|
873
|
+
else
|
874
|
+
{
|
875
|
+
SystemError(theEnv,"RULEBLD",2);
|
876
|
+
ExitRouter(theEnv,EXIT_FAILURE);
|
877
|
+
}
|
878
|
+
}
|
879
|
+
|
880
|
+
/*==============================================*/
|
881
|
+
/* Unhandled case which should not be possible. */
|
882
|
+
/*==============================================*/
|
883
|
+
|
884
|
+
else
|
885
|
+
{
|
886
|
+
SystemError(theEnv,"RULEBLD",3);
|
887
|
+
ExitRouter(theEnv,EXIT_FAILURE);
|
888
|
+
}
|
889
|
+
|
890
|
+
/*=================================================*/
|
891
|
+
/* Remove the TEST CE and continue to the next CE. */
|
892
|
+
/*=================================================*/
|
893
|
+
|
894
|
+
theLHS->networkTest = NULL;
|
895
|
+
tempNode = theLHS->bottom;
|
896
|
+
theLHS->bottom = NULL;
|
897
|
+
lastNode->bottom = tempNode;
|
898
|
+
lastNode->endNandDepth = theLHS->endNandDepth;
|
899
|
+
ReturnLHSParseNodes(theEnv,theLHS);
|
900
|
+
theLHS = tempNode;
|
901
|
+
}
|
902
|
+
}
|
903
|
+
|
904
|
+
/********************************************************************/
|
905
|
+
/* FindShareableJoin: Determines whether a join exists that can be */
|
906
|
+
/* reused for the join currently being added to the join network. */
|
907
|
+
/* Returns a pointer to the join to be shared if one if found, */
|
908
|
+
/* otherwise returns a NULL pointer. */
|
909
|
+
/********************************************************************/
|
910
|
+
static struct joinNode *FindShareableJoin(
|
911
|
+
struct joinLink *theLinks,
|
912
|
+
struct joinNode *listOfJoins,
|
913
|
+
bool useLinks,
|
914
|
+
void *rhsStruct,
|
915
|
+
bool firstJoin,
|
916
|
+
bool negatedRHS,
|
917
|
+
bool existsRHS,
|
918
|
+
bool isLogical,
|
919
|
+
struct expr *joinTest,
|
920
|
+
struct expr *secondaryJoinTest,
|
921
|
+
struct expr *leftHash,
|
922
|
+
struct expr *rightHash)
|
923
|
+
{
|
924
|
+
/*========================================*/
|
925
|
+
/* Loop through all of the joins in the */
|
926
|
+
/* list of potential candiates for reuse. */
|
927
|
+
/*========================================*/
|
928
|
+
|
929
|
+
if (useLinks)
|
930
|
+
{
|
931
|
+
if (theLinks != NULL)
|
932
|
+
{ listOfJoins = theLinks->join; }
|
933
|
+
else
|
934
|
+
{ listOfJoins = NULL; }
|
935
|
+
}
|
936
|
+
|
937
|
+
while (listOfJoins != NULL)
|
938
|
+
{
|
939
|
+
/*=========================================================*/
|
940
|
+
/* If the join being tested for reuse is connected on the */
|
941
|
+
/* RHS to the end node of the pattern node associated with */
|
942
|
+
/* the join to be added, then determine if the join can */
|
943
|
+
/* be reused. If so, return the join. */
|
944
|
+
/*=========================================================*/
|
945
|
+
|
946
|
+
if (listOfJoins->rightSideEntryStructure == rhsStruct)
|
947
|
+
{
|
948
|
+
if (TestJoinForReuse(listOfJoins,firstJoin,negatedRHS,existsRHS,
|
949
|
+
isLogical,joinTest,secondaryJoinTest,
|
950
|
+
leftHash,rightHash))
|
951
|
+
{ return(listOfJoins); }
|
952
|
+
}
|
953
|
+
|
954
|
+
/*====================================================*/
|
955
|
+
/* Move on to the next potential candidate. Note that */
|
956
|
+
/* the rightMatchNode link is used for traversing */
|
957
|
+
/* through the candidates for the first join of a */
|
958
|
+
/* rule and that rightDriveNode link is used for */
|
959
|
+
/* traversing through the candidates for subsequent */
|
960
|
+
/* joins of a rule. */
|
961
|
+
/*====================================================*/
|
962
|
+
|
963
|
+
if (useLinks)
|
964
|
+
{
|
965
|
+
theLinks = theLinks->next;
|
966
|
+
if (theLinks != NULL)
|
967
|
+
{ listOfJoins = theLinks->join; }
|
968
|
+
else
|
969
|
+
{ listOfJoins = NULL; }
|
970
|
+
}
|
971
|
+
else
|
972
|
+
{ listOfJoins = listOfJoins->rightMatchNode; }
|
973
|
+
}
|
974
|
+
|
975
|
+
/*================================*/
|
976
|
+
/* Return a NULL pointer, since a */
|
977
|
+
/* reusable join was not found. */
|
978
|
+
/*================================*/
|
979
|
+
|
980
|
+
return NULL;
|
981
|
+
}
|
982
|
+
|
983
|
+
/**************************************************************/
|
984
|
+
/* TestJoinForReuse: Determines if the specified join can be */
|
985
|
+
/* shared with a join being added for a rule being defined. */
|
986
|
+
/* Returns true if the join can be shared, otherwise false. */
|
987
|
+
/**************************************************************/
|
988
|
+
static bool TestJoinForReuse(
|
989
|
+
struct joinNode *testJoin,
|
990
|
+
bool firstJoin,
|
991
|
+
bool negatedRHS,
|
992
|
+
bool existsRHS,
|
993
|
+
bool isLogical,
|
994
|
+
struct expr *joinTest,
|
995
|
+
struct expr *secondaryJoinTest,
|
996
|
+
struct expr *leftHash,
|
997
|
+
struct expr *rightHash)
|
998
|
+
{
|
999
|
+
/*==================================================*/
|
1000
|
+
/* The first join of a rule may only be shared with */
|
1001
|
+
/* a join that has its firstJoin field set to true. */
|
1002
|
+
/*==================================================*/
|
1003
|
+
|
1004
|
+
if (testJoin->firstJoin != firstJoin) return false;
|
1005
|
+
|
1006
|
+
/*========================================================*/
|
1007
|
+
/* A join connected to a not CE may only be shared with a */
|
1008
|
+
/* join that has its patternIsNegated field set to true. */
|
1009
|
+
/*========================================================*/
|
1010
|
+
|
1011
|
+
if ((testJoin->patternIsNegated != negatedRHS) && (! existsRHS)) return false;
|
1012
|
+
|
1013
|
+
/*==========================================================*/
|
1014
|
+
/* A join connected to an exists CE may only be shared with */
|
1015
|
+
/* a join that has its patternIsExists field set to true. */
|
1016
|
+
/*==========================================================*/
|
1017
|
+
|
1018
|
+
if (testJoin->patternIsExists != existsRHS) return false;
|
1019
|
+
|
1020
|
+
/*==========================================================*/
|
1021
|
+
/* If the join added is associated with a logical CE, then */
|
1022
|
+
/* either the join to be shared must be associated with a */
|
1023
|
+
/* logical CE or the beta memory must be empty (since */
|
1024
|
+
/* joins associate an extra field with each partial match). */
|
1025
|
+
/*==========================================================*/
|
1026
|
+
|
1027
|
+
if ((isLogical == true) &&
|
1028
|
+
(testJoin->logicalJoin == false) &&
|
1029
|
+
BetaMemoryNotEmpty(testJoin))
|
1030
|
+
{ return false; }
|
1031
|
+
|
1032
|
+
/*===============================================================*/
|
1033
|
+
/* The expression associated with the join must be identical to */
|
1034
|
+
/* the networkTest expression stored with the join to be shared. */
|
1035
|
+
/*===============================================================*/
|
1036
|
+
|
1037
|
+
if (IdenticalExpression(testJoin->networkTest,joinTest) != true)
|
1038
|
+
{ return false; }
|
1039
|
+
|
1040
|
+
if (IdenticalExpression(testJoin->secondaryNetworkTest,secondaryJoinTest) != true)
|
1041
|
+
{ return false; }
|
1042
|
+
|
1043
|
+
/*====================================================================*/
|
1044
|
+
/* The alpha memory hashing values associated with the join must be */
|
1045
|
+
/* identical to the hashing values stored with the join to be shared. */
|
1046
|
+
/*====================================================================*/
|
1047
|
+
|
1048
|
+
if (IdenticalExpression(testJoin->leftHash,leftHash) != true)
|
1049
|
+
{ return false; }
|
1050
|
+
|
1051
|
+
if (IdenticalExpression(testJoin->rightHash,rightHash) != true)
|
1052
|
+
{ return false; }
|
1053
|
+
|
1054
|
+
/*=============================================*/
|
1055
|
+
/* The join can be shared since all conditions */
|
1056
|
+
/* for sharing have been satisfied. */
|
1057
|
+
/*=============================================*/
|
1058
|
+
|
1059
|
+
return true;
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
/*************************************************************************/
|
1063
|
+
/* CreateNewJoin: Creates a new join and links it into the join network. */
|
1064
|
+
/*************************************************************************/
|
1065
|
+
static struct joinNode *CreateNewJoin(
|
1066
|
+
Environment *theEnv,
|
1067
|
+
struct expr *joinTest,
|
1068
|
+
struct expr *secondaryJoinTest,
|
1069
|
+
struct joinNode *lhsEntryStruct,
|
1070
|
+
void *rhsEntryStruct,
|
1071
|
+
bool joinFromTheRight,
|
1072
|
+
bool negatedRHSPattern,
|
1073
|
+
bool existsRHSPattern,
|
1074
|
+
struct expr *leftHash,
|
1075
|
+
struct expr *rightHash)
|
1076
|
+
{
|
1077
|
+
struct joinNode *newJoin;
|
1078
|
+
struct joinLink *theLink;
|
1079
|
+
|
1080
|
+
/*===============================================*/
|
1081
|
+
/* If compilations are being watch, print +j to */
|
1082
|
+
/* indicate that a new join has been created for */
|
1083
|
+
/* this pattern of the rule (i.e. a join could */
|
1084
|
+
/* not be shared with another rule. */
|
1085
|
+
/*===============================================*/
|
1086
|
+
|
1087
|
+
#if DEBUGGING_FUNCTIONS
|
1088
|
+
if ((GetWatchItem(theEnv,"compilations") == 1) && GetPrintWhileLoading(theEnv))
|
1089
|
+
{ WriteString(theEnv,STDOUT,"+j"); }
|
1090
|
+
#endif
|
1091
|
+
|
1092
|
+
/*======================*/
|
1093
|
+
/* Create the new join. */
|
1094
|
+
/*======================*/
|
1095
|
+
|
1096
|
+
newJoin = get_struct(theEnv,joinNode);
|
1097
|
+
|
1098
|
+
/*======================================================*/
|
1099
|
+
/* The first join of a rule does not have a beta memory */
|
1100
|
+
/* unless the RHS pattern is an exists or not CE. */
|
1101
|
+
/*======================================================*/
|
1102
|
+
|
1103
|
+
if ((lhsEntryStruct != NULL) || existsRHSPattern || negatedRHSPattern || joinFromTheRight)
|
1104
|
+
{
|
1105
|
+
if (leftHash == NULL)
|
1106
|
+
{
|
1107
|
+
newJoin->leftMemory = get_struct(theEnv,betaMemory);
|
1108
|
+
newJoin->leftMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
|
1109
|
+
newJoin->leftMemory->beta[0] = NULL;
|
1110
|
+
newJoin->leftMemory->last = NULL;
|
1111
|
+
newJoin->leftMemory->size = 1;
|
1112
|
+
newJoin->leftMemory->count = 0;
|
1113
|
+
}
|
1114
|
+
else
|
1115
|
+
{
|
1116
|
+
newJoin->leftMemory = get_struct(theEnv,betaMemory);
|
1117
|
+
newJoin->leftMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
|
1118
|
+
memset(newJoin->leftMemory->beta,0,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
|
1119
|
+
newJoin->leftMemory->last = NULL;
|
1120
|
+
newJoin->leftMemory->size = INITIAL_BETA_HASH_SIZE;
|
1121
|
+
newJoin->leftMemory->count = 0;
|
1122
|
+
}
|
1123
|
+
|
1124
|
+
/*===========================================================*/
|
1125
|
+
/* If the first join of a rule connects to an exists or not */
|
1126
|
+
/* CE, then we create an empty partial match for the usually */
|
1127
|
+
/* empty left beta memory so that we can track the current */
|
1128
|
+
/* current right memory partial match satisfying the CE. */
|
1129
|
+
/*===========================================================*/
|
1130
|
+
|
1131
|
+
if ((lhsEntryStruct == NULL) && (existsRHSPattern || negatedRHSPattern || joinFromTheRight))
|
1132
|
+
{
|
1133
|
+
newJoin->leftMemory->beta[0] = CreateEmptyPartialMatch(theEnv);
|
1134
|
+
newJoin->leftMemory->beta[0]->owner = newJoin;
|
1135
|
+
newJoin->leftMemory->count = 1;
|
1136
|
+
}
|
1137
|
+
}
|
1138
|
+
else
|
1139
|
+
{ newJoin->leftMemory = NULL; }
|
1140
|
+
|
1141
|
+
if (joinFromTheRight)
|
1142
|
+
{
|
1143
|
+
if (leftHash == NULL)
|
1144
|
+
{
|
1145
|
+
newJoin->rightMemory = get_struct(theEnv,betaMemory);
|
1146
|
+
newJoin->rightMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
|
1147
|
+
newJoin->rightMemory->last = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
|
1148
|
+
newJoin->rightMemory->beta[0] = NULL;
|
1149
|
+
newJoin->rightMemory->last[0] = NULL;
|
1150
|
+
newJoin->rightMemory->size = 1;
|
1151
|
+
newJoin->rightMemory->count = 0;
|
1152
|
+
}
|
1153
|
+
else
|
1154
|
+
{
|
1155
|
+
newJoin->rightMemory = get_struct(theEnv,betaMemory);
|
1156
|
+
newJoin->rightMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
|
1157
|
+
newJoin->rightMemory->last = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
|
1158
|
+
memset(newJoin->rightMemory->beta,0,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
|
1159
|
+
memset(newJoin->rightMemory->last,0,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
|
1160
|
+
newJoin->rightMemory->size = INITIAL_BETA_HASH_SIZE;
|
1161
|
+
newJoin->rightMemory->count = 0;
|
1162
|
+
}
|
1163
|
+
}
|
1164
|
+
else if (rhsEntryStruct == NULL)
|
1165
|
+
{
|
1166
|
+
newJoin->rightMemory = get_struct(theEnv,betaMemory);
|
1167
|
+
newJoin->rightMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
|
1168
|
+
newJoin->rightMemory->last = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
|
1169
|
+
newJoin->rightMemory->beta[0] = CreateEmptyPartialMatch(theEnv);
|
1170
|
+
newJoin->rightMemory->beta[0]->owner = newJoin;
|
1171
|
+
newJoin->rightMemory->beta[0]->rhsMemory = true;
|
1172
|
+
newJoin->rightMemory->last[0] = newJoin->rightMemory->beta[0];
|
1173
|
+
newJoin->rightMemory->size = 1;
|
1174
|
+
newJoin->rightMemory->count = 1;
|
1175
|
+
}
|
1176
|
+
else
|
1177
|
+
{ newJoin->rightMemory = NULL; }
|
1178
|
+
|
1179
|
+
newJoin->nextLinks = NULL;
|
1180
|
+
newJoin->joinFromTheRight = joinFromTheRight;
|
1181
|
+
|
1182
|
+
if (existsRHSPattern)
|
1183
|
+
{ newJoin->patternIsNegated = false; }
|
1184
|
+
else
|
1185
|
+
{ newJoin->patternIsNegated = negatedRHSPattern; }
|
1186
|
+
newJoin->patternIsExists = existsRHSPattern;
|
1187
|
+
|
1188
|
+
newJoin->marked = false;
|
1189
|
+
newJoin->initialize = true;
|
1190
|
+
newJoin->logicalJoin = false;
|
1191
|
+
newJoin->ruleToActivate = NULL;
|
1192
|
+
newJoin->memoryLeftAdds = 0;
|
1193
|
+
newJoin->memoryRightAdds = 0;
|
1194
|
+
newJoin->memoryLeftDeletes = 0;
|
1195
|
+
newJoin->memoryRightDeletes = 0;
|
1196
|
+
newJoin->memoryCompares = 0;
|
1197
|
+
|
1198
|
+
/*==============================================*/
|
1199
|
+
/* Install the expressions used to determine */
|
1200
|
+
/* if a partial match satisfies the constraints */
|
1201
|
+
/* associated with this join. */
|
1202
|
+
/*==============================================*/
|
1203
|
+
|
1204
|
+
newJoin->networkTest = AddHashedExpression(theEnv,joinTest);
|
1205
|
+
newJoin->secondaryNetworkTest = AddHashedExpression(theEnv,secondaryJoinTest);
|
1206
|
+
|
1207
|
+
/*=====================================================*/
|
1208
|
+
/* Install the expression used to hash the beta memory */
|
1209
|
+
/* partial match to determine the location to search */
|
1210
|
+
/* in the alpha memory. */
|
1211
|
+
/*=====================================================*/
|
1212
|
+
|
1213
|
+
newJoin->leftHash = AddHashedExpression(theEnv,leftHash);
|
1214
|
+
newJoin->rightHash = AddHashedExpression(theEnv,rightHash);
|
1215
|
+
|
1216
|
+
/*============================================================*/
|
1217
|
+
/* Initialize the values associated with the LHS of the join. */
|
1218
|
+
/*============================================================*/
|
1219
|
+
|
1220
|
+
newJoin->lastLevel = lhsEntryStruct;
|
1221
|
+
|
1222
|
+
if (lhsEntryStruct == NULL)
|
1223
|
+
{
|
1224
|
+
newJoin->firstJoin = true;
|
1225
|
+
newJoin->depth = 1;
|
1226
|
+
}
|
1227
|
+
else
|
1228
|
+
{
|
1229
|
+
newJoin->firstJoin = false;
|
1230
|
+
newJoin->depth = lhsEntryStruct->depth;
|
1231
|
+
newJoin->depth++; /* To work around Sparcworks C compiler bug */
|
1232
|
+
|
1233
|
+
theLink = get_struct(theEnv,joinLink);
|
1234
|
+
theLink->join = newJoin;
|
1235
|
+
theLink->enterDirection = LHS;
|
1236
|
+
|
1237
|
+
/*==============================================================*/
|
1238
|
+
/* If this is a join from the right, then there should already */
|
1239
|
+
/* be a link from the previous join to the other join in the */
|
1240
|
+
/* the bifurcated path through the join network. If so, we want */
|
1241
|
+
/* add the next link to the join from the right so that it is */
|
1242
|
+
/* visited after the other path. Doing this will reduce the */
|
1243
|
+
/* number of activations added and then removed if the other */
|
1244
|
+
/* path were followed first. The other path generates the */
|
1245
|
+
/* partial matches which are negated by this path, so if that */
|
1246
|
+
/* path is processed first, the partial matches from that path */
|
1247
|
+
/* will prevent partial matches on this path. */
|
1248
|
+
/*==============================================================*/
|
1249
|
+
|
1250
|
+
if ((joinFromTheRight) && (lhsEntryStruct->nextLinks != NULL))
|
1251
|
+
{
|
1252
|
+
theLink->next = lhsEntryStruct->nextLinks->next;
|
1253
|
+
lhsEntryStruct->nextLinks->next = theLink;
|
1254
|
+
}
|
1255
|
+
else
|
1256
|
+
{
|
1257
|
+
theLink->next = lhsEntryStruct->nextLinks;
|
1258
|
+
lhsEntryStruct->nextLinks = theLink;
|
1259
|
+
}
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
/*=======================================================*/
|
1263
|
+
/* Initialize the pointer values associated with the RHS */
|
1264
|
+
/* of the join (both for the new join and the join or */
|
1265
|
+
/* pattern which enters this join from the right. */
|
1266
|
+
/*=======================================================*/
|
1267
|
+
|
1268
|
+
newJoin->rightSideEntryStructure = rhsEntryStruct;
|
1269
|
+
|
1270
|
+
if (rhsEntryStruct == NULL)
|
1271
|
+
{
|
1272
|
+
if (newJoin->firstJoin)
|
1273
|
+
{
|
1274
|
+
theLink = get_struct(theEnv,joinLink);
|
1275
|
+
theLink->join = newJoin;
|
1276
|
+
theLink->enterDirection = RHS;
|
1277
|
+
theLink->next = DefruleData(theEnv)->RightPrimeJoins;
|
1278
|
+
DefruleData(theEnv)->RightPrimeJoins = theLink;
|
1279
|
+
}
|
1280
|
+
|
1281
|
+
newJoin->rightMatchNode = NULL;
|
1282
|
+
|
1283
|
+
return(newJoin);
|
1284
|
+
}
|
1285
|
+
|
1286
|
+
/*===========================================================*/
|
1287
|
+
/* If the first join of a rule is a not CE, then it needs to */
|
1288
|
+
/* be "primed" under certain circumstances. This used to be */
|
1289
|
+
/* handled by adding the (initial-fact) pattern to a rule */
|
1290
|
+
/* with the not CE as its first pattern, but this alternate */
|
1291
|
+
/* mechanism is now used so patterns don't have to be added. */
|
1292
|
+
/*===========================================================*/
|
1293
|
+
|
1294
|
+
if (newJoin->firstJoin && (newJoin->patternIsNegated || newJoin->joinFromTheRight) && (! newJoin->patternIsExists))
|
1295
|
+
{
|
1296
|
+
theLink = get_struct(theEnv,joinLink);
|
1297
|
+
theLink->join = newJoin;
|
1298
|
+
theLink->enterDirection = LHS;
|
1299
|
+
theLink->next = DefruleData(theEnv)->LeftPrimeJoins;
|
1300
|
+
DefruleData(theEnv)->LeftPrimeJoins = theLink;
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
if (joinFromTheRight)
|
1304
|
+
{
|
1305
|
+
theLink = get_struct(theEnv,joinLink);
|
1306
|
+
theLink->join = newJoin;
|
1307
|
+
theLink->enterDirection = RHS;
|
1308
|
+
theLink->next = ((struct joinNode *) rhsEntryStruct)->nextLinks;
|
1309
|
+
((struct joinNode *) rhsEntryStruct)->nextLinks = theLink;
|
1310
|
+
newJoin->rightMatchNode = NULL;
|
1311
|
+
}
|
1312
|
+
else
|
1313
|
+
{
|
1314
|
+
newJoin->rightMatchNode = ((struct patternNodeHeader *) rhsEntryStruct)->entryJoin;
|
1315
|
+
((struct patternNodeHeader *) rhsEntryStruct)->entryJoin = newJoin;
|
1316
|
+
}
|
1317
|
+
|
1318
|
+
/*================================*/
|
1319
|
+
/* Return the newly created join. */
|
1320
|
+
/*================================*/
|
1321
|
+
|
1322
|
+
return(newJoin);
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
#endif
|
1326
|
+
|
1327
|
+
|
1328
|
+
|