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,1035 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.40 12/07/17 */
|
5
|
+
/* */
|
6
|
+
/* FACT BUILD MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: Given a new fact pattern, adds the pattern to */
|
11
|
+
/* the pattern network of the associated deftemplate. Also */
|
12
|
+
/* contains routines for deleting a pattern from the fact */
|
13
|
+
/* pattern network. */
|
14
|
+
/* */
|
15
|
+
/* Principal Programmer(s): */
|
16
|
+
/* Gary D. Riley */
|
17
|
+
/* */
|
18
|
+
/* Contributing Programmer(s): */
|
19
|
+
/* */
|
20
|
+
/* Revision History: */
|
21
|
+
/* */
|
22
|
+
/* 6.24: Removed INCREMENTAL_RESET compilation flag. */
|
23
|
+
/* */
|
24
|
+
/* 6.30: Added support for hashed alpha memories. */
|
25
|
+
/* */
|
26
|
+
/* Added support for hashed comparisons to */
|
27
|
+
/* constants. */
|
28
|
+
/* */
|
29
|
+
/* 6.40: Pragma once and other inclusion changes. */
|
30
|
+
/* */
|
31
|
+
/* Added support for booleans with <stdbool.h>. */
|
32
|
+
/* */
|
33
|
+
/* Removed use of void pointers for specific */
|
34
|
+
/* data structures. */
|
35
|
+
/* */
|
36
|
+
/* Removed initial-fact support. */
|
37
|
+
/* */
|
38
|
+
/*************************************************************/
|
39
|
+
|
40
|
+
#include "setup.h"
|
41
|
+
|
42
|
+
#if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT
|
43
|
+
|
44
|
+
#include <stdio.h>
|
45
|
+
|
46
|
+
#include "argacces.h"
|
47
|
+
#include "envrnmnt.h"
|
48
|
+
#include "factcmp.h"
|
49
|
+
#include "factgen.h"
|
50
|
+
#include "factlhs.h"
|
51
|
+
#include "factmch.h"
|
52
|
+
#include "factmngr.h"
|
53
|
+
#include "memalloc.h"
|
54
|
+
#include "modulutl.h"
|
55
|
+
#include "reorder.h"
|
56
|
+
#include "reteutil.h"
|
57
|
+
#include "router.h"
|
58
|
+
#include "tmpltdef.h"
|
59
|
+
|
60
|
+
#include "factbld.h"
|
61
|
+
|
62
|
+
/***************************************/
|
63
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
64
|
+
/***************************************/
|
65
|
+
|
66
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
67
|
+
static struct factPatternNode *FindPatternNode(struct factPatternNode *,struct lhsParseNode *,
|
68
|
+
struct factPatternNode **,bool,bool);
|
69
|
+
static struct factPatternNode *CreateNewPatternNode(Environment *,struct lhsParseNode *,struct factPatternNode *,
|
70
|
+
struct factPatternNode *,bool,bool);
|
71
|
+
static void ClearPatternMatches(Environment *,struct factPatternNode *);
|
72
|
+
static void DetachFactPattern(Environment *,struct patternNodeHeader *);
|
73
|
+
static struct patternNodeHeader *PlaceFactPattern(Environment *,struct lhsParseNode *);
|
74
|
+
static struct lhsParseNode *RemoveUnneededSlots(Environment *,struct lhsParseNode *);
|
75
|
+
static void FindAndSetDeftemplatePatternNetwork(Environment *,struct factPatternNode *,struct factPatternNode *);
|
76
|
+
#endif
|
77
|
+
|
78
|
+
/*********************************************************/
|
79
|
+
/* InitializeFactPatterns: Adds fact patterns to the set */
|
80
|
+
/* of patterns recognized by the rule pattern parsing */
|
81
|
+
/* and pattern/join network integration routines. */
|
82
|
+
/*********************************************************/
|
83
|
+
void InitializeFactPatterns(
|
84
|
+
Environment *theEnv)
|
85
|
+
{
|
86
|
+
#if DEFRULE_CONSTRUCT
|
87
|
+
struct patternParser *newPtr;
|
88
|
+
|
89
|
+
InitializeFactReteFunctions(theEnv);
|
90
|
+
|
91
|
+
newPtr = get_struct(theEnv,patternParser);
|
92
|
+
|
93
|
+
newPtr->name = "facts";
|
94
|
+
newPtr->priority = 0;
|
95
|
+
newPtr->entityType = &FactData(theEnv)->FactInfo;
|
96
|
+
|
97
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
98
|
+
newPtr->recognizeFunction = FactPatternParserFind;
|
99
|
+
newPtr->parseFunction = FactPatternParse;
|
100
|
+
newPtr->postAnalysisFunction = NULL;
|
101
|
+
newPtr->addPatternFunction = PlaceFactPattern;
|
102
|
+
newPtr->removePatternFunction = DetachFactPattern;
|
103
|
+
newPtr->genJNConstantFunction = NULL;
|
104
|
+
newPtr->replaceGetJNValueFunction = FactReplaceGetvar;
|
105
|
+
newPtr->genGetJNValueFunction = FactGenGetvar;
|
106
|
+
newPtr->genCompareJNValuesFunction = FactJNVariableComparison;
|
107
|
+
newPtr->genPNConstantFunction = FactGenPNConstant;
|
108
|
+
newPtr->replaceGetPNValueFunction = FactReplaceGetfield;
|
109
|
+
newPtr->genGetPNValueFunction = FactGenGetfield;
|
110
|
+
newPtr->genComparePNValuesFunction = FactPNVariableComparison;
|
111
|
+
newPtr->returnUserDataFunction = NULL;
|
112
|
+
newPtr->copyUserDataFunction = NULL;
|
113
|
+
#else
|
114
|
+
newPtr->recognizeFunction = NULL;
|
115
|
+
newPtr->parseFunction = NULL;
|
116
|
+
newPtr->postAnalysisFunction = NULL;
|
117
|
+
newPtr->addPatternFunction = NULL;
|
118
|
+
newPtr->removePatternFunction = NULL;
|
119
|
+
newPtr->genJNConstantFunction = NULL;
|
120
|
+
newPtr->replaceGetJNValueFunction = NULL;
|
121
|
+
newPtr->genGetJNValueFunction = NULL;
|
122
|
+
newPtr->genCompareJNValuesFunction = NULL;
|
123
|
+
newPtr->genPNConstantFunction = NULL;
|
124
|
+
newPtr->replaceGetPNValueFunction = NULL;
|
125
|
+
newPtr->genGetPNValueFunction = NULL;
|
126
|
+
newPtr->genComparePNValuesFunction = NULL;
|
127
|
+
newPtr->returnUserDataFunction = NULL;
|
128
|
+
newPtr->copyUserDataFunction = NULL;
|
129
|
+
#endif
|
130
|
+
|
131
|
+
newPtr->markIRPatternFunction = MarkFactPatternForIncrementalReset;
|
132
|
+
newPtr->incrementalResetFunction = FactsIncrementalReset;
|
133
|
+
|
134
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
135
|
+
#if CONSTRUCT_COMPILER
|
136
|
+
newPtr->codeReferenceFunction = FactPatternNodeReference;
|
137
|
+
#else
|
138
|
+
newPtr->codeReferenceFunction = NULL;
|
139
|
+
#endif
|
140
|
+
#else
|
141
|
+
newPtr->codeReferenceFunction = NULL;
|
142
|
+
#endif
|
143
|
+
|
144
|
+
AddPatternParser(theEnv,newPtr);
|
145
|
+
#endif
|
146
|
+
}
|
147
|
+
|
148
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
149
|
+
|
150
|
+
/******************************************************************************/
|
151
|
+
/* PlaceFactPattern: Integrates a fact pattern into the fact pattern network. */
|
152
|
+
/******************************************************************************/
|
153
|
+
static struct patternNodeHeader *PlaceFactPattern(
|
154
|
+
Environment *theEnv,
|
155
|
+
struct lhsParseNode *thePattern)
|
156
|
+
{
|
157
|
+
struct lhsParseNode *tempPattern;
|
158
|
+
struct factPatternNode *currentLevel, *lastLevel;
|
159
|
+
struct factPatternNode *nodeBeforeMatch, *newNode = NULL;
|
160
|
+
bool endSlot;
|
161
|
+
unsigned int count;
|
162
|
+
const char *deftemplateName;
|
163
|
+
|
164
|
+
/*======================================================================*/
|
165
|
+
/* Get the name of the deftemplate associated with the pattern being */
|
166
|
+
/* added (recall that the first field of any pattern must be a symbol). */
|
167
|
+
/*======================================================================*/
|
168
|
+
|
169
|
+
deftemplateName = thePattern->right->bottom->lexemeValue->contents;
|
170
|
+
|
171
|
+
/*=====================================================*/
|
172
|
+
/* Remove any slot tests that test only for existance. */
|
173
|
+
/*=====================================================*/
|
174
|
+
|
175
|
+
thePattern->right = RemoveUnneededSlots(theEnv,thePattern->right);
|
176
|
+
|
177
|
+
/*========================================================*/
|
178
|
+
/* If the constant test for the relation name is the only */
|
179
|
+
/* pattern network test and there are no other network */
|
180
|
+
/* tests, then remove the test, but keep the node since */
|
181
|
+
/* there must be a link from the fact pattern network to */
|
182
|
+
/* the join network. Otherwise, remove the test for the */
|
183
|
+
/* relation name since this test has already been done */
|
184
|
+
/* before entering the pattern network (since each */
|
185
|
+
/* deftemplate has its own pattern network). */
|
186
|
+
/*========================================================*/
|
187
|
+
|
188
|
+
if (thePattern->right->right == NULL)
|
189
|
+
{
|
190
|
+
ReturnExpression(theEnv,thePattern->right->networkTest);
|
191
|
+
ReturnExpression(theEnv,thePattern->right->constantSelector);
|
192
|
+
ReturnExpression(theEnv,thePattern->right->constantValue);
|
193
|
+
thePattern->right->networkTest = NULL;
|
194
|
+
thePattern->right->constantSelector = NULL;
|
195
|
+
thePattern->right->constantValue = NULL;
|
196
|
+
}
|
197
|
+
else
|
198
|
+
{
|
199
|
+
tempPattern = thePattern->right;
|
200
|
+
thePattern->right = thePattern->right->right;
|
201
|
+
tempPattern->right = NULL;
|
202
|
+
ReturnLHSParseNodes(theEnv,tempPattern);
|
203
|
+
}
|
204
|
+
|
205
|
+
/*====================================================*/
|
206
|
+
/* Get the expression for hashing in the alpha memory */
|
207
|
+
/* and attach it to the last node of the pattern. */
|
208
|
+
/*====================================================*/
|
209
|
+
|
210
|
+
tempPattern = thePattern->right;
|
211
|
+
while (tempPattern->right != NULL)
|
212
|
+
{ tempPattern = tempPattern->right; }
|
213
|
+
|
214
|
+
if ((tempPattern->multifieldSlot) && (tempPattern->bottom != NULL))
|
215
|
+
{
|
216
|
+
tempPattern = tempPattern->bottom;
|
217
|
+
|
218
|
+
while (tempPattern->right != NULL)
|
219
|
+
{ tempPattern = tempPattern->right; }
|
220
|
+
}
|
221
|
+
|
222
|
+
tempPattern->rightHash = thePattern->rightHash;
|
223
|
+
thePattern->rightHash = NULL;
|
224
|
+
|
225
|
+
tempPattern = NULL;
|
226
|
+
|
227
|
+
/*============================================================*/
|
228
|
+
/* Get a pointer to the deftemplate data structure associated */
|
229
|
+
/* with the pattern (use the deftemplate name extracted from */
|
230
|
+
/* the first field of the pattern). */
|
231
|
+
/*============================================================*/
|
232
|
+
|
233
|
+
FactData(theEnv)->CurrentDeftemplate = (Deftemplate *)
|
234
|
+
FindImportedConstruct(theEnv,"deftemplate",NULL,
|
235
|
+
deftemplateName,&count,
|
236
|
+
true,NULL);
|
237
|
+
|
238
|
+
/*================================================*/
|
239
|
+
/* Initialize some pointers to indicate where the */
|
240
|
+
/* pattern is being added to the pattern network. */
|
241
|
+
/*================================================*/
|
242
|
+
|
243
|
+
currentLevel = FactData(theEnv)->CurrentDeftemplate->patternNetwork;
|
244
|
+
lastLevel = NULL;
|
245
|
+
thePattern = thePattern->right;
|
246
|
+
|
247
|
+
/*===========================================*/
|
248
|
+
/* Loop until all fields in the pattern have */
|
249
|
+
/* been added to the pattern network. */
|
250
|
+
/*===========================================*/
|
251
|
+
|
252
|
+
while (thePattern != NULL)
|
253
|
+
{
|
254
|
+
/*===========================================================*/
|
255
|
+
/* If a multifield slot is being processed, then process the */
|
256
|
+
/* pattern nodes attached to the multifield pattern node. */
|
257
|
+
/*===========================================================*/
|
258
|
+
|
259
|
+
if (thePattern->multifieldSlot)
|
260
|
+
{
|
261
|
+
tempPattern = thePattern;
|
262
|
+
thePattern = thePattern->bottom;
|
263
|
+
}
|
264
|
+
|
265
|
+
/*============================================*/
|
266
|
+
/* Determine if the last pattern field within */
|
267
|
+
/* a multifield slot is being processed. */
|
268
|
+
/*============================================*/
|
269
|
+
|
270
|
+
if ((thePattern->right == NULL) && (tempPattern != NULL))
|
271
|
+
{ endSlot = true; }
|
272
|
+
else
|
273
|
+
{ endSlot = false; }
|
274
|
+
|
275
|
+
/*========================================*/
|
276
|
+
/* Is there a node in the pattern network */
|
277
|
+
/* that can be reused (shared)? */
|
278
|
+
/*========================================*/
|
279
|
+
|
280
|
+
newNode = FindPatternNode(currentLevel,thePattern,&nodeBeforeMatch,endSlot,false);
|
281
|
+
|
282
|
+
/*================================================*/
|
283
|
+
/* If the pattern node cannot be shared, then add */
|
284
|
+
/* a new pattern node to the pattern network. */
|
285
|
+
/*================================================*/
|
286
|
+
|
287
|
+
if (newNode == NULL)
|
288
|
+
{ newNode = CreateNewPatternNode(theEnv,thePattern,nodeBeforeMatch,lastLevel,endSlot,false); }
|
289
|
+
|
290
|
+
if (thePattern->constantSelector != NULL)
|
291
|
+
{
|
292
|
+
currentLevel = newNode->nextLevel;
|
293
|
+
lastLevel = newNode;
|
294
|
+
newNode = FindPatternNode(currentLevel,thePattern,&nodeBeforeMatch,endSlot,true);
|
295
|
+
|
296
|
+
if (newNode == NULL)
|
297
|
+
{ newNode = CreateNewPatternNode(theEnv,thePattern,nodeBeforeMatch,lastLevel,endSlot,true); }
|
298
|
+
}
|
299
|
+
|
300
|
+
/*===========================================================*/
|
301
|
+
/* Move on to the next field in the new pattern to be added. */
|
302
|
+
/*===========================================================*/
|
303
|
+
|
304
|
+
if ((thePattern->right == NULL) && (tempPattern != NULL))
|
305
|
+
{
|
306
|
+
thePattern = tempPattern;
|
307
|
+
tempPattern = NULL;
|
308
|
+
}
|
309
|
+
|
310
|
+
thePattern = thePattern->right;
|
311
|
+
|
312
|
+
/*==========================================================*/
|
313
|
+
/* If there are no more pattern nodes to be added to the */
|
314
|
+
/* pattern network, then mark the last pattern node added */
|
315
|
+
/* as a stop node (i.e. if you get to this node and the */
|
316
|
+
/* network test succeeds, then a pattern has been matched). */
|
317
|
+
/*==========================================================*/
|
318
|
+
|
319
|
+
if (thePattern == NULL) newNode->header.stopNode = true;
|
320
|
+
|
321
|
+
/*================================================*/
|
322
|
+
/* Update the pointers which indicate where we're */
|
323
|
+
/* trying to add the new pattern to the currently */
|
324
|
+
/* existing pattern network. */
|
325
|
+
/*================================================*/
|
326
|
+
|
327
|
+
lastLevel = newNode;
|
328
|
+
currentLevel = newNode->nextLevel;
|
329
|
+
}
|
330
|
+
|
331
|
+
/*==================================================*/
|
332
|
+
/* Return the leaf node of the newly added pattern. */
|
333
|
+
/*==================================================*/
|
334
|
+
|
335
|
+
return((struct patternNodeHeader *) newNode);
|
336
|
+
}
|
337
|
+
|
338
|
+
/*************************************************************/
|
339
|
+
/* FindPatternNode: Looks for a pattern node at a specified */
|
340
|
+
/* level in the pattern network that can be reused (shared) */
|
341
|
+
/* with a pattern field being added to the pattern network. */
|
342
|
+
/*************************************************************/
|
343
|
+
static struct factPatternNode *FindPatternNode(
|
344
|
+
struct factPatternNode *listOfNodes,
|
345
|
+
struct lhsParseNode *thePattern,
|
346
|
+
struct factPatternNode **nodeBeforeMatch,
|
347
|
+
bool endSlot,
|
348
|
+
bool constantSelector)
|
349
|
+
{
|
350
|
+
struct expr *compareTest;
|
351
|
+
*nodeBeforeMatch = NULL;
|
352
|
+
|
353
|
+
if (constantSelector)
|
354
|
+
{ compareTest = thePattern->constantValue; }
|
355
|
+
else if (thePattern->constantSelector != NULL)
|
356
|
+
{ compareTest = thePattern->constantSelector; }
|
357
|
+
else
|
358
|
+
{ compareTest = thePattern->networkTest; }
|
359
|
+
|
360
|
+
/*==========================================================*/
|
361
|
+
/* Loop through the nodes at the given level in the pattern */
|
362
|
+
/* network looking for a node that can be reused (shared)? */
|
363
|
+
/*==========================================================*/
|
364
|
+
|
365
|
+
while (listOfNodes != NULL)
|
366
|
+
{
|
367
|
+
/*==========================================================*/
|
368
|
+
/* If the type of the pattern node and the expression being */
|
369
|
+
/* tested by the pattern node are the same as the type and */
|
370
|
+
/* expression for the pattern field being added, then */
|
371
|
+
/* return the pattern node because it can be shared with */
|
372
|
+
/* the pattern field being added. */
|
373
|
+
/*==========================================================*/
|
374
|
+
|
375
|
+
if ((thePattern->pnType == SF_WILDCARD_NODE) || (thePattern->pnType == SF_VARIABLE_NODE))
|
376
|
+
{
|
377
|
+
if ((listOfNodes->header.singlefieldNode) &&
|
378
|
+
(listOfNodes->header.endSlot == endSlot) &&
|
379
|
+
(listOfNodes->whichField == thePattern->index) &&
|
380
|
+
(listOfNodes->whichSlot == (thePattern->slotNumber - 1)) &&
|
381
|
+
IdenticalExpression(listOfNodes->networkTest,compareTest) &&
|
382
|
+
IdenticalExpression(listOfNodes->header.rightHash,thePattern->rightHash))
|
383
|
+
{ return(listOfNodes); }
|
384
|
+
}
|
385
|
+
else if ((thePattern->pnType == MF_WILDCARD_NODE) || (thePattern->pnType == MF_VARIABLE_NODE))
|
386
|
+
{
|
387
|
+
if ((listOfNodes->header.multifieldNode) &&
|
388
|
+
(listOfNodes->header.endSlot == endSlot) &&
|
389
|
+
(listOfNodes->leaveFields == thePattern->singleFieldsAfter) &&
|
390
|
+
(listOfNodes->whichField == thePattern->index) &&
|
391
|
+
(listOfNodes->whichSlot == (thePattern->slotNumber - 1)) &&
|
392
|
+
IdenticalExpression(listOfNodes->networkTest,compareTest) &&
|
393
|
+
IdenticalExpression(listOfNodes->header.rightHash,thePattern->rightHash))
|
394
|
+
{ return(listOfNodes); }
|
395
|
+
}
|
396
|
+
|
397
|
+
/*==================================*/
|
398
|
+
/* Move on to the next node at this */
|
399
|
+
/* level in the pattern network. */
|
400
|
+
/*==================================*/
|
401
|
+
|
402
|
+
*nodeBeforeMatch = listOfNodes;
|
403
|
+
listOfNodes = listOfNodes->rightNode;
|
404
|
+
}
|
405
|
+
|
406
|
+
/*==============================================*/
|
407
|
+
/* A shareable pattern node could not be found. */
|
408
|
+
/*==============================================*/
|
409
|
+
|
410
|
+
return NULL;
|
411
|
+
}
|
412
|
+
|
413
|
+
/*************************************************************/
|
414
|
+
/* RemoveUnneededSlots: Removes fact pattern nodes that have */
|
415
|
+
/* no effect on pattern matching. For example, given the */
|
416
|
+
/* following deftemplate and a pattern using it, */
|
417
|
+
/* */
|
418
|
+
/* (deftemplate foo (slot x) (slot y)) */
|
419
|
+
/* */
|
420
|
+
/* (foo (x ?x) (y ?y)) */
|
421
|
+
/* */
|
422
|
+
/* The x and y slot pattern nodes can be discarded since */
|
423
|
+
/* all foo facts will have these two slots in the fact */
|
424
|
+
/* data structure used to store them. */
|
425
|
+
/*************************************************************/
|
426
|
+
static struct lhsParseNode *RemoveUnneededSlots(
|
427
|
+
Environment *theEnv,
|
428
|
+
struct lhsParseNode *thePattern)
|
429
|
+
{
|
430
|
+
struct lhsParseNode *tempPattern = thePattern;
|
431
|
+
struct lhsParseNode *lastPattern = NULL, *head = thePattern;
|
432
|
+
struct expr *theTest;
|
433
|
+
|
434
|
+
while (tempPattern != NULL)
|
435
|
+
{
|
436
|
+
/*=============================================================*/
|
437
|
+
/* A single field slot that has no pattern network expression */
|
438
|
+
/* associated with it can be removed (i.e. any value contained */
|
439
|
+
/* in this slot will satisfy the pattern being matched). */
|
440
|
+
/*=============================================================*/
|
441
|
+
|
442
|
+
if (((tempPattern->pnType == SF_WILDCARD_NODE) || (tempPattern->pnType == SF_VARIABLE_NODE)) &&
|
443
|
+
(tempPattern->networkTest == NULL))
|
444
|
+
{
|
445
|
+
if (lastPattern != NULL) lastPattern->right = tempPattern->right;
|
446
|
+
else head = tempPattern->right;
|
447
|
+
|
448
|
+
tempPattern->right = NULL;
|
449
|
+
ReturnLHSParseNodes(theEnv,tempPattern);
|
450
|
+
|
451
|
+
if (lastPattern != NULL) tempPattern = lastPattern->right;
|
452
|
+
else tempPattern = head;
|
453
|
+
}
|
454
|
+
|
455
|
+
/*=======================================================*/
|
456
|
+
/* A multifield variable or wildcard within a multifield */
|
457
|
+
/* slot can be removed if there are no other multifield */
|
458
|
+
/* variables or wildcards contained in the same slot */
|
459
|
+
/* (and the multifield has no expressions which must be */
|
460
|
+
/* evaluated in the fact pattern network). */
|
461
|
+
/*=======================================================*/
|
462
|
+
|
463
|
+
else if (((tempPattern->pnType == MF_WILDCARD_NODE) || (tempPattern->pnType == MF_VARIABLE_NODE)) &&
|
464
|
+
(tempPattern->multifieldSlot == false) &&
|
465
|
+
(tempPattern->networkTest == NULL) &&
|
466
|
+
(tempPattern->multiFieldsBefore == 0) &&
|
467
|
+
(tempPattern->multiFieldsAfter == 0))
|
468
|
+
{
|
469
|
+
if (lastPattern != NULL) lastPattern->right = tempPattern->right;
|
470
|
+
else head = tempPattern->right;
|
471
|
+
|
472
|
+
tempPattern->right = NULL;
|
473
|
+
ReturnLHSParseNodes(theEnv,tempPattern);
|
474
|
+
|
475
|
+
if (lastPattern != NULL) tempPattern = lastPattern->right;
|
476
|
+
else tempPattern = head;
|
477
|
+
}
|
478
|
+
|
479
|
+
/*==================================================================*/
|
480
|
+
/* A multifield wildcard or variable contained in a multifield slot */
|
481
|
+
/* that contains no other multifield wildcards or variables, but */
|
482
|
+
/* does have an expression that must be evaluated, can be changed */
|
483
|
+
/* to a single field pattern node with the same expression. */
|
484
|
+
/*==================================================================*/
|
485
|
+
|
486
|
+
else if (((tempPattern->pnType == MF_WILDCARD_NODE) || (tempPattern->pnType == MF_VARIABLE_NODE)) &&
|
487
|
+
(tempPattern->multifieldSlot == false) &&
|
488
|
+
(tempPattern->networkTest != NULL) &&
|
489
|
+
(tempPattern->multiFieldsBefore == 0) &&
|
490
|
+
(tempPattern->multiFieldsAfter == 0))
|
491
|
+
{
|
492
|
+
tempPattern->pnType = SF_WILDCARD_NODE;
|
493
|
+
lastPattern = tempPattern;
|
494
|
+
tempPattern = tempPattern->right;
|
495
|
+
}
|
496
|
+
|
497
|
+
/*=========================================================*/
|
498
|
+
/* If we're dealing with a multifield slot with no slot */
|
499
|
+
/* restrictions, then treat the multfield slot as a single */
|
500
|
+
/* field slot, but attach a test which verifies that the */
|
501
|
+
/* slot contains a zero length multifield value. */
|
502
|
+
/*=========================================================*/
|
503
|
+
|
504
|
+
else if ((tempPattern->pnType == MF_WILDCARD_NODE) &&
|
505
|
+
(tempPattern->multifieldSlot == true) &&
|
506
|
+
(tempPattern->bottom == NULL))
|
507
|
+
{
|
508
|
+
tempPattern->pnType = SF_WILDCARD_NODE;
|
509
|
+
tempPattern->networkTest = FactGenCheckZeroLength(theEnv,tempPattern->slotNumber);
|
510
|
+
tempPattern->multifieldSlot = false;
|
511
|
+
lastPattern = tempPattern;
|
512
|
+
tempPattern = tempPattern->right;
|
513
|
+
}
|
514
|
+
|
515
|
+
/*===================================================*/
|
516
|
+
/* Recursively call RemoveUnneededSlots for the slot */
|
517
|
+
/* restrictions contained within a multifield slot. */
|
518
|
+
/*===================================================*/
|
519
|
+
|
520
|
+
else if ((tempPattern->pnType == MF_WILDCARD_NODE) &&
|
521
|
+
(tempPattern->multifieldSlot == true))
|
522
|
+
{
|
523
|
+
/*=======================================================*/
|
524
|
+
/* Add an expression to the first pattern restriction in */
|
525
|
+
/* the multifield slot that determines whether or not */
|
526
|
+
/* the fact's slot value contains the minimum number of */
|
527
|
+
/* required fields to satisfy the pattern restrictions */
|
528
|
+
/* for this slot. The length check is place before any */
|
529
|
+
/* other tests, so that preceeding checks do not have to */
|
530
|
+
/* determine if there are enough fields in the slot to */
|
531
|
+
/* safely retrieve a value. */
|
532
|
+
/*=======================================================*/
|
533
|
+
|
534
|
+
theTest = FactGenCheckLength(theEnv,tempPattern->bottom);
|
535
|
+
if (tempPattern->bottom->constantSelector != NULL)
|
536
|
+
{ tempPattern->bottom->constantSelector->nextArg = CopyExpression(theEnv,theTest); }
|
537
|
+
theTest = CombineExpressions(theEnv,theTest,tempPattern->bottom->networkTest);
|
538
|
+
tempPattern->bottom->networkTest = theTest;
|
539
|
+
|
540
|
+
/*=========================================================*/
|
541
|
+
/* Remove any unneeded pattern restrictions from the slot. */
|
542
|
+
/*=========================================================*/
|
543
|
+
|
544
|
+
tempPattern->bottom = RemoveUnneededSlots(theEnv,tempPattern->bottom);
|
545
|
+
|
546
|
+
/*===========================================================*/
|
547
|
+
/* If the slot no longer contains any restrictions, then the */
|
548
|
+
/* multifield slot can be completely removed. In any case, */
|
549
|
+
/* move on to the next slot to be examined for removal. */
|
550
|
+
/*===========================================================*/
|
551
|
+
|
552
|
+
if (tempPattern->bottom == NULL)
|
553
|
+
{
|
554
|
+
if (lastPattern != NULL) lastPattern->right = tempPattern->right;
|
555
|
+
else head = tempPattern->right;
|
556
|
+
|
557
|
+
tempPattern->right = NULL;
|
558
|
+
ReturnLHSParseNodes(theEnv,tempPattern);
|
559
|
+
|
560
|
+
if (lastPattern != NULL) tempPattern = lastPattern->right;
|
561
|
+
else tempPattern = head;
|
562
|
+
}
|
563
|
+
else
|
564
|
+
{
|
565
|
+
lastPattern = tempPattern;
|
566
|
+
tempPattern = tempPattern->right;
|
567
|
+
}
|
568
|
+
}
|
569
|
+
|
570
|
+
/*=======================================================*/
|
571
|
+
/* If none of the other tests for removing slots or slot */
|
572
|
+
/* restrictions apply, then move on to the next slot or */
|
573
|
+
/* slot restriction to be tested. */
|
574
|
+
/*=======================================================*/
|
575
|
+
|
576
|
+
else
|
577
|
+
{
|
578
|
+
lastPattern = tempPattern;
|
579
|
+
tempPattern = tempPattern->right;
|
580
|
+
}
|
581
|
+
}
|
582
|
+
|
583
|
+
/*======================================*/
|
584
|
+
/* Return the pattern with unused slots */
|
585
|
+
/* and slot restrictions removed. */
|
586
|
+
/*======================================*/
|
587
|
+
|
588
|
+
return(head);
|
589
|
+
}
|
590
|
+
|
591
|
+
/****************************************************/
|
592
|
+
/* CreateNewPatternNode: Creates a new pattern node */
|
593
|
+
/* and initializes all of its values. */
|
594
|
+
/****************************************************/
|
595
|
+
static struct factPatternNode *CreateNewPatternNode(
|
596
|
+
Environment *theEnv,
|
597
|
+
struct lhsParseNode *thePattern,
|
598
|
+
struct factPatternNode *nodeBeforeMatch,
|
599
|
+
struct factPatternNode *upperLevel,
|
600
|
+
bool endSlot,
|
601
|
+
bool constantSelector)
|
602
|
+
{
|
603
|
+
struct factPatternNode *newNode;
|
604
|
+
|
605
|
+
/*========================================*/
|
606
|
+
/* Create the pattern node and initialize */
|
607
|
+
/* its slots to the default values. */
|
608
|
+
/*========================================*/
|
609
|
+
|
610
|
+
newNode = get_struct(theEnv,factPatternNode);
|
611
|
+
newNode->nextLevel = NULL;
|
612
|
+
newNode->rightNode = NULL;
|
613
|
+
newNode->leftNode = NULL;
|
614
|
+
newNode->leaveFields = thePattern->singleFieldsAfter;
|
615
|
+
InitializePatternHeader(theEnv,(struct patternNodeHeader *) &newNode->header);
|
616
|
+
|
617
|
+
if (thePattern->index > 0)
|
618
|
+
{ newNode->whichField = thePattern->index; }
|
619
|
+
else newNode->whichField = 0;
|
620
|
+
|
621
|
+
if (thePattern->slotNumber != UNSPECIFIED_SLOT)
|
622
|
+
{ newNode->whichSlot = thePattern->slotNumber - 1; }
|
623
|
+
else
|
624
|
+
{ newNode->whichSlot = newNode->whichField; }
|
625
|
+
|
626
|
+
if ((thePattern->constantSelector != NULL) && (! constantSelector))
|
627
|
+
{ newNode->header.selector = true; }
|
628
|
+
|
629
|
+
/*=============================================================*/
|
630
|
+
/* Set the slot values which indicate whether the pattern node */
|
631
|
+
/* is a single-field, multifield, or end-of-pattern node. */
|
632
|
+
/*=============================================================*/
|
633
|
+
|
634
|
+
if ((thePattern->pnType == SF_WILDCARD_NODE) || (thePattern->pnType == SF_VARIABLE_NODE))
|
635
|
+
{ newNode->header.singlefieldNode = true; }
|
636
|
+
else if ((thePattern->pnType == MF_WILDCARD_NODE) || (thePattern->pnType == MF_VARIABLE_NODE))
|
637
|
+
{ newNode->header.multifieldNode = true; }
|
638
|
+
newNode->header.endSlot = endSlot;
|
639
|
+
|
640
|
+
/*===========================================================*/
|
641
|
+
/* Install the expression associated with this pattern node. */
|
642
|
+
/*===========================================================*/
|
643
|
+
|
644
|
+
if (constantSelector)
|
645
|
+
{ newNode->networkTest = AddHashedExpression(theEnv,thePattern->constantValue); }
|
646
|
+
else if (thePattern->constantSelector != NULL)
|
647
|
+
{ newNode->networkTest = AddHashedExpression(theEnv,thePattern->constantSelector); }
|
648
|
+
else
|
649
|
+
{ newNode->networkTest = AddHashedExpression(theEnv,thePattern->networkTest); }
|
650
|
+
|
651
|
+
/*==========================================*/
|
652
|
+
/* Add the expression used for adding alpha */
|
653
|
+
/* matches to the alpha memory. */
|
654
|
+
/*==========================================*/
|
655
|
+
|
656
|
+
newNode->header.rightHash = AddHashedExpression(theEnv,thePattern->rightHash);
|
657
|
+
|
658
|
+
/*===============================================*/
|
659
|
+
/* Set the upper level pointer for the new node. */
|
660
|
+
/*===============================================*/
|
661
|
+
|
662
|
+
newNode->lastLevel = upperLevel;
|
663
|
+
|
664
|
+
if ((upperLevel != NULL) && (upperLevel->header.selector))
|
665
|
+
{ AddHashedPatternNode(theEnv,upperLevel,newNode,newNode->networkTest->type,newNode->networkTest->value); }
|
666
|
+
|
667
|
+
/*======================================================*/
|
668
|
+
/* If there are no nodes on this level, then attach the */
|
669
|
+
/* new node to the child pointer of the upper level. */
|
670
|
+
/*======================================================*/
|
671
|
+
|
672
|
+
if (nodeBeforeMatch == NULL)
|
673
|
+
{
|
674
|
+
if (upperLevel == NULL) FactData(theEnv)->CurrentDeftemplate->patternNetwork = newNode;
|
675
|
+
else upperLevel->nextLevel = newNode;
|
676
|
+
return(newNode);
|
677
|
+
}
|
678
|
+
|
679
|
+
/*=====================================================*/
|
680
|
+
/* If there is an upper level above the new node, then */
|
681
|
+
/* place the new node as the first child in the upper */
|
682
|
+
/* level's nextLevel (child) link. */
|
683
|
+
/*=====================================================*/
|
684
|
+
|
685
|
+
if (upperLevel != NULL)
|
686
|
+
{
|
687
|
+
newNode->rightNode = upperLevel->nextLevel;
|
688
|
+
if (upperLevel->nextLevel != NULL)
|
689
|
+
{ upperLevel->nextLevel->leftNode = newNode; }
|
690
|
+
upperLevel->nextLevel = newNode;
|
691
|
+
return(newNode);
|
692
|
+
}
|
693
|
+
|
694
|
+
/*=====================================================*/
|
695
|
+
/* Since there is no upper level above the new node, */
|
696
|
+
/* (i.e. the new node is being added to the highest */
|
697
|
+
/* level in the pattern network), the new node becomes */
|
698
|
+
/* the first node visited in the pattern network. */
|
699
|
+
/*=====================================================*/
|
700
|
+
|
701
|
+
newNode->rightNode = FactData(theEnv)->CurrentDeftemplate->patternNetwork;
|
702
|
+
if (FactData(theEnv)->CurrentDeftemplate->patternNetwork != NULL)
|
703
|
+
{ FactData(theEnv)->CurrentDeftemplate->patternNetwork->leftNode = newNode; }
|
704
|
+
|
705
|
+
FactData(theEnv)->CurrentDeftemplate->patternNetwork = newNode;
|
706
|
+
return(newNode);
|
707
|
+
}
|
708
|
+
|
709
|
+
/*************************************************************/
|
710
|
+
/* DetachFactPattern: Removes a pattern node and all of its */
|
711
|
+
/* parent nodes from the pattern network. Nodes are only */
|
712
|
+
/* removed if they are no longer shared (i.e. a pattern */
|
713
|
+
/* node that has more than one child node is shared). A */
|
714
|
+
/* pattern from a rule is typically removed by removing */
|
715
|
+
/* the bottom most pattern node used by the pattern and */
|
716
|
+
/* then removing any parent nodes which are not shared by */
|
717
|
+
/* other patterns. */
|
718
|
+
/* */
|
719
|
+
/* Example: */
|
720
|
+
/* Patterns (a b c d) and (a b e f) would be represented */
|
721
|
+
/* by the pattern net shown on the left. If (a b c d) */
|
722
|
+
/* was detached, the resultant pattern net would be the */
|
723
|
+
/* one shown on the right. */
|
724
|
+
/* */
|
725
|
+
/* a a */
|
726
|
+
/* | | */
|
727
|
+
/* b b */
|
728
|
+
/* | | */
|
729
|
+
/* c--e e */
|
730
|
+
/* | | | */
|
731
|
+
/* d f f */
|
732
|
+
/* */
|
733
|
+
/*************************************************************/
|
734
|
+
static void DetachFactPattern(
|
735
|
+
Environment *theEnv,
|
736
|
+
struct patternNodeHeader *thePattern)
|
737
|
+
{
|
738
|
+
struct factPatternNode *patternPtr;
|
739
|
+
struct factPatternNode *upperLevel;
|
740
|
+
|
741
|
+
/*=====================================================*/
|
742
|
+
/* Get rid of any matches stored in the alpha memory. */
|
743
|
+
/*=====================================================*/
|
744
|
+
|
745
|
+
patternPtr = (struct factPatternNode *) thePattern;
|
746
|
+
ClearPatternMatches(theEnv,patternPtr);
|
747
|
+
|
748
|
+
/*=======================================================*/
|
749
|
+
/* If there are no joins entered from this pattern, then */
|
750
|
+
/* the pattern node is no longer a stop node. Also if */
|
751
|
+
/* the pattern has a next level pointer, then it can */
|
752
|
+
/* not be removed since other patterns make use of it. */
|
753
|
+
/*=======================================================*/
|
754
|
+
|
755
|
+
if (patternPtr->header.entryJoin == NULL) patternPtr->header.stopNode = false;
|
756
|
+
if (patternPtr->nextLevel != NULL) return;
|
757
|
+
|
758
|
+
/*==============================================================*/
|
759
|
+
/* Loop until all appropriate pattern nodes have been detached. */
|
760
|
+
/*==============================================================*/
|
761
|
+
|
762
|
+
upperLevel = patternPtr;
|
763
|
+
while (upperLevel != NULL)
|
764
|
+
{
|
765
|
+
if ((upperLevel->leftNode == NULL) &&
|
766
|
+
(upperLevel->rightNode == NULL))
|
767
|
+
{
|
768
|
+
/*===============================================*/
|
769
|
+
/* Pattern node is the only node on this level. */
|
770
|
+
/* Remove it and continue detaching other nodes */
|
771
|
+
/* above this one, because no other patterns are */
|
772
|
+
/* dependent upon this node. */
|
773
|
+
/*===============================================*/
|
774
|
+
|
775
|
+
patternPtr = upperLevel;
|
776
|
+
upperLevel = patternPtr->lastLevel;
|
777
|
+
|
778
|
+
if (upperLevel == NULL)
|
779
|
+
{ FindAndSetDeftemplatePatternNetwork(theEnv,patternPtr,NULL); }
|
780
|
+
else
|
781
|
+
{
|
782
|
+
if (upperLevel->header.selector)
|
783
|
+
{ RemoveHashedPatternNode(theEnv,upperLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
|
784
|
+
|
785
|
+
upperLevel->nextLevel = NULL;
|
786
|
+
if (upperLevel->header.stopNode) upperLevel = NULL;
|
787
|
+
}
|
788
|
+
|
789
|
+
RemoveHashedExpression(theEnv,patternPtr->networkTest);
|
790
|
+
RemoveHashedExpression(theEnv,patternPtr->header.rightHash);
|
791
|
+
rtn_struct(theEnv,factPatternNode,patternPtr);
|
792
|
+
}
|
793
|
+
else if (upperLevel->leftNode != NULL)
|
794
|
+
{
|
795
|
+
/*====================================================*/
|
796
|
+
/* Pattern node has another pattern node which must */
|
797
|
+
/* be checked preceding it. Remove the pattern node, */
|
798
|
+
/* but do not detach any nodes above this one. */
|
799
|
+
/*====================================================*/
|
800
|
+
|
801
|
+
patternPtr = upperLevel;
|
802
|
+
|
803
|
+
if ((patternPtr->lastLevel != NULL) &&
|
804
|
+
(patternPtr->lastLevel->header.selector))
|
805
|
+
{ RemoveHashedPatternNode(theEnv,patternPtr->lastLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
|
806
|
+
|
807
|
+
upperLevel->leftNode->rightNode = upperLevel->rightNode;
|
808
|
+
if (upperLevel->rightNode != NULL)
|
809
|
+
{ upperLevel->rightNode->leftNode = upperLevel->leftNode; }
|
810
|
+
|
811
|
+
RemoveHashedExpression(theEnv,patternPtr->networkTest);
|
812
|
+
RemoveHashedExpression(theEnv,patternPtr->header.rightHash);
|
813
|
+
rtn_struct(theEnv,factPatternNode,patternPtr);
|
814
|
+
upperLevel = NULL;
|
815
|
+
}
|
816
|
+
else
|
817
|
+
{
|
818
|
+
/*====================================================*/
|
819
|
+
/* Pattern node has no pattern node preceding it, but */
|
820
|
+
/* does have one succeeding it. Remove the pattern */
|
821
|
+
/* node, but do not detach any nodes above this one. */
|
822
|
+
/*====================================================*/
|
823
|
+
|
824
|
+
patternPtr = upperLevel;
|
825
|
+
upperLevel = upperLevel->lastLevel;
|
826
|
+
if (upperLevel == NULL)
|
827
|
+
{ FindAndSetDeftemplatePatternNetwork(theEnv,patternPtr,patternPtr->rightNode); }
|
828
|
+
else
|
829
|
+
{
|
830
|
+
if (upperLevel->header.selector)
|
831
|
+
{ RemoveHashedPatternNode(theEnv,upperLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
|
832
|
+
|
833
|
+
upperLevel->nextLevel = patternPtr->rightNode;
|
834
|
+
}
|
835
|
+
patternPtr->rightNode->leftNode = NULL;
|
836
|
+
|
837
|
+
RemoveHashedExpression(theEnv,patternPtr->networkTest);
|
838
|
+
RemoveHashedExpression(theEnv,patternPtr->header.rightHash);
|
839
|
+
rtn_struct(theEnv,factPatternNode,patternPtr);
|
840
|
+
upperLevel = NULL;
|
841
|
+
}
|
842
|
+
}
|
843
|
+
}
|
844
|
+
|
845
|
+
#endif
|
846
|
+
|
847
|
+
/**************************************************************/
|
848
|
+
/* DestroyFactPatternNetwork: Deallocates the data structures */
|
849
|
+
/* associated with a fact pattern network. */
|
850
|
+
/**************************************************************/
|
851
|
+
void DestroyFactPatternNetwork(
|
852
|
+
Environment *theEnv,
|
853
|
+
struct factPatternNode *thePattern)
|
854
|
+
{
|
855
|
+
struct factPatternNode *patternPtr;
|
856
|
+
|
857
|
+
if (thePattern == NULL) return;
|
858
|
+
|
859
|
+
while (thePattern != NULL)
|
860
|
+
{
|
861
|
+
patternPtr = thePattern->rightNode;
|
862
|
+
|
863
|
+
DestroyFactPatternNetwork(theEnv,thePattern->nextLevel);
|
864
|
+
|
865
|
+
DestroyAlphaMemory(theEnv,&thePattern->header,false);
|
866
|
+
|
867
|
+
if ((thePattern->lastLevel != NULL) &&
|
868
|
+
(thePattern->lastLevel->header.selector))
|
869
|
+
{ RemoveHashedPatternNode(theEnv,thePattern->lastLevel,thePattern,thePattern->networkTest->type,thePattern->networkTest->value); }
|
870
|
+
|
871
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
872
|
+
rtn_struct(theEnv,factPatternNode,thePattern);
|
873
|
+
#endif
|
874
|
+
|
875
|
+
thePattern = patternPtr;
|
876
|
+
}
|
877
|
+
}
|
878
|
+
|
879
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
880
|
+
|
881
|
+
/***********************************************************/
|
882
|
+
/* FindAndSetDeftemplatePatternNetwork: When a deftemplate */
|
883
|
+
/* pattern is detached from the fact pattern network, it */
|
884
|
+
/* is not possible to directly detach the link from the */
|
885
|
+
/* deftemplate to the pattern network (it is a one way */
|
886
|
+
/* link). Therefore if the top most pointer to a */
|
887
|
+
/* deftemplates pattern network must be changed, it is */
|
888
|
+
/* necessary to search the list of deftemplates to find */
|
889
|
+
/* the appropriate one to modify. */
|
890
|
+
/***********************************************************/
|
891
|
+
static void FindAndSetDeftemplatePatternNetwork(
|
892
|
+
Environment *theEnv,
|
893
|
+
struct factPatternNode *rootNode,
|
894
|
+
struct factPatternNode *newRootNode)
|
895
|
+
{
|
896
|
+
Deftemplate *theDeftemplate;
|
897
|
+
Defmodule *theModule;
|
898
|
+
|
899
|
+
/*=======================================================*/
|
900
|
+
/* Save the current module since we will be changing it. */
|
901
|
+
/*=======================================================*/
|
902
|
+
|
903
|
+
SaveCurrentModule(theEnv);
|
904
|
+
|
905
|
+
/*=======================================================*/
|
906
|
+
/* Loop through every module looking for the deftemplate */
|
907
|
+
/* associated with the specified root node. */
|
908
|
+
/*=======================================================*/
|
909
|
+
|
910
|
+
for (theModule = GetNextDefmodule(theEnv,NULL);
|
911
|
+
theModule != NULL;
|
912
|
+
theModule = GetNextDefmodule(theEnv,theModule))
|
913
|
+
{
|
914
|
+
/*======================================================*/
|
915
|
+
/* Set the current module to the module being examined. */
|
916
|
+
/*======================================================*/
|
917
|
+
|
918
|
+
SetCurrentModule(theEnv,theModule);
|
919
|
+
|
920
|
+
/*======================================================*/
|
921
|
+
/* Loop through every deftemplate in the current module */
|
922
|
+
/* searching for the deftemplate associated with the */
|
923
|
+
/* specified root node. */
|
924
|
+
/*======================================================*/
|
925
|
+
|
926
|
+
for (theDeftemplate = GetNextDeftemplate(theEnv,NULL);
|
927
|
+
theDeftemplate != NULL;
|
928
|
+
theDeftemplate = GetNextDeftemplate(theEnv,theDeftemplate))
|
929
|
+
{
|
930
|
+
/*===========================================================*/
|
931
|
+
/* When the associated deftemplate is found, change its root */
|
932
|
+
/* node from the current value to the new value. Restore the */
|
933
|
+
/* current module before leaving this routine. */
|
934
|
+
/*===========================================================*/
|
935
|
+
|
936
|
+
if (theDeftemplate->patternNetwork == rootNode)
|
937
|
+
{
|
938
|
+
RestoreCurrentModule(theEnv);
|
939
|
+
theDeftemplate->patternNetwork = newRootNode;
|
940
|
+
return;
|
941
|
+
}
|
942
|
+
}
|
943
|
+
}
|
944
|
+
|
945
|
+
/*========================================================*/
|
946
|
+
/* If the deftemplate wasn't found, then we're presumably */
|
947
|
+
/* we're in the the middle of a clear and the deftemplate */
|
948
|
+
/* has already been deleted so there's no need to update */
|
949
|
+
/* the links to the fact pattern network. */
|
950
|
+
/*========================================================*/
|
951
|
+
|
952
|
+
RestoreCurrentModule(theEnv);
|
953
|
+
}
|
954
|
+
|
955
|
+
/***************************************************************/
|
956
|
+
/* ClearPatternMatches: Clears the fact list of all pointers */
|
957
|
+
/* which point to a specific pattern. The pointers are used */
|
958
|
+
/* to remember which patterns were matched by a fact to */
|
959
|
+
/* make retraction easier. When a rule is excised, the */
|
960
|
+
/* pointers need to be removed. */
|
961
|
+
/***************************************************************/
|
962
|
+
static void ClearPatternMatches(
|
963
|
+
Environment *theEnv,
|
964
|
+
struct factPatternNode *patternPtr)
|
965
|
+
{
|
966
|
+
Fact *theFact;
|
967
|
+
struct patternMatch *lastMatch, *theMatch;
|
968
|
+
|
969
|
+
/*===========================================*/
|
970
|
+
/* Loop through every fact in the fact list. */
|
971
|
+
/*===========================================*/
|
972
|
+
|
973
|
+
for (theFact = GetNextFact(theEnv,NULL);
|
974
|
+
theFact != NULL;
|
975
|
+
theFact = GetNextFact(theEnv,theFact))
|
976
|
+
{
|
977
|
+
/*========================================*/
|
978
|
+
/* Loop through every match for the fact. */
|
979
|
+
/*========================================*/
|
980
|
+
|
981
|
+
lastMatch = NULL;
|
982
|
+
theMatch = (struct patternMatch *) theFact->list;
|
983
|
+
|
984
|
+
while (theMatch != NULL)
|
985
|
+
{
|
986
|
+
/*================================================*/
|
987
|
+
/* If the match is for the pattern being deleted, */
|
988
|
+
/* then remove the match. */
|
989
|
+
/*================================================*/
|
990
|
+
|
991
|
+
if (theMatch->matchingPattern == (struct patternNodeHeader *) patternPtr)
|
992
|
+
{
|
993
|
+
if (lastMatch == NULL)
|
994
|
+
{
|
995
|
+
/*=====================================*/
|
996
|
+
/* Remove the first match of the fact. */
|
997
|
+
/*=====================================*/
|
998
|
+
|
999
|
+
theFact->list = theMatch->next;
|
1000
|
+
rtn_struct(theEnv,patternMatch,theMatch);
|
1001
|
+
theMatch = (struct patternMatch *) theFact->list;
|
1002
|
+
}
|
1003
|
+
else
|
1004
|
+
{
|
1005
|
+
/*===================================*/
|
1006
|
+
/* Remove a match for the fact which */
|
1007
|
+
/* follows the first match. */
|
1008
|
+
/*===================================*/
|
1009
|
+
|
1010
|
+
lastMatch->next = theMatch->next;
|
1011
|
+
rtn_struct(theEnv,patternMatch,theMatch);
|
1012
|
+
theMatch = lastMatch->next;
|
1013
|
+
}
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
/*====================================================*/
|
1017
|
+
/* If the match is not for the pattern being deleted, */
|
1018
|
+
/* then move on to the next match for the fact. */
|
1019
|
+
/*====================================================*/
|
1020
|
+
|
1021
|
+
else
|
1022
|
+
{
|
1023
|
+
lastMatch = theMatch;
|
1024
|
+
theMatch = theMatch->next;
|
1025
|
+
}
|
1026
|
+
}
|
1027
|
+
}
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
#endif /* (! RUN_TIME) && (! BLOAD_ONLY) */
|
1031
|
+
|
1032
|
+
#endif /* DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT */
|
1033
|
+
|
1034
|
+
|
1035
|
+
|