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,1524 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.41 07/12/21 */
|
5
|
+
/* */
|
6
|
+
/* OBJECT PATTERN MATCHER MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: RETE Network Interface for Objects */
|
11
|
+
/* */
|
12
|
+
/* Principal Programmer(s): */
|
13
|
+
/* Brian L. Dantes */
|
14
|
+
/* */
|
15
|
+
/* Contributing Programmer(s): */
|
16
|
+
/* */
|
17
|
+
/* Revision History: */
|
18
|
+
/* */
|
19
|
+
/* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
|
20
|
+
/* */
|
21
|
+
/* 6.24: Removed INCREMENTAL_RESET and */
|
22
|
+
/* LOGICAL_DEPENDENCIES compilation flags. */
|
23
|
+
/* */
|
24
|
+
/* Converted INSTANCE_PATTERN_MATCHING to */
|
25
|
+
/* DEFRULE_CONSTRUCT. */
|
26
|
+
/* */
|
27
|
+
/* Renamed BOOLEAN macro type to intBool. */
|
28
|
+
/* */
|
29
|
+
/* 6.30: Modified the QueueObjectMatchAction function */
|
30
|
+
/* so that instance retract actions always occur */
|
31
|
+
/* before instance assert and modify actions. */
|
32
|
+
/* This prevents the pattern matching process */
|
33
|
+
/* from attempting the evaluation of a join */
|
34
|
+
/* expression that accesses the slots of a */
|
35
|
+
/* retracted instance. */
|
36
|
+
/* */
|
37
|
+
/* Added support for hashed alpha memories. */
|
38
|
+
/* */
|
39
|
+
/* Support for long long integers. */
|
40
|
+
/* */
|
41
|
+
/* Added support for hashed comparisons to */
|
42
|
+
/* constants. */
|
43
|
+
/* */
|
44
|
+
/* 6.31: Optimization for marking relevant alpha nodes */
|
45
|
+
/* in the object pattern network. */
|
46
|
+
/* */
|
47
|
+
/* 6.32: Fixed instance redefinition crash with rules */
|
48
|
+
/* in JNSimpleCompareFunction1 when deleted */
|
49
|
+
/* instance slots are referenced. */
|
50
|
+
/* */
|
51
|
+
/* 6.40: Added Env prefix to GetEvaluationError and */
|
52
|
+
/* SetEvaluationError functions. */
|
53
|
+
/* */
|
54
|
+
/* Added Env prefix to GetHaltExecution and */
|
55
|
+
/* SetHaltExecution functions. */
|
56
|
+
/* */
|
57
|
+
/* Pragma once and other inclusion changes. */
|
58
|
+
/* */
|
59
|
+
/* Added support for booleans with <stdbool.h>. */
|
60
|
+
/* */
|
61
|
+
/* Removed use of void pointers for specific */
|
62
|
+
/* data structures. */
|
63
|
+
/* */
|
64
|
+
/* UDF redesign. */
|
65
|
+
/* */
|
66
|
+
/* 6.41: Added Env prefix to GetEvaluationError and */
|
67
|
+
/* SetEvaluationError functions. */
|
68
|
+
/* */
|
69
|
+
/*************************************************************/
|
70
|
+
/* =========================================
|
71
|
+
*****************************************
|
72
|
+
EXTERNAL DEFINITIONS
|
73
|
+
=========================================
|
74
|
+
***************************************** */
|
75
|
+
#include "setup.h"
|
76
|
+
|
77
|
+
#if DEFRULE_CONSTRUCT && OBJECT_SYSTEM
|
78
|
+
|
79
|
+
#include "classfun.h"
|
80
|
+
#include "memalloc.h"
|
81
|
+
#include "drive.h"
|
82
|
+
#include "engine.h"
|
83
|
+
#include "envrnmnt.h"
|
84
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
85
|
+
#include "incrrset.h"
|
86
|
+
#endif
|
87
|
+
#include "lgcldpnd.h"
|
88
|
+
#include "multifld.h"
|
89
|
+
#include "objrtfnx.h"
|
90
|
+
#include "objrtmch.h"
|
91
|
+
#include "prntutil.h"
|
92
|
+
#include "reteutil.h"
|
93
|
+
#include "ruledlt.h"
|
94
|
+
#include "reorder.h"
|
95
|
+
#include "retract.h"
|
96
|
+
#include "router.h"
|
97
|
+
|
98
|
+
#include "insmngr.h"
|
99
|
+
|
100
|
+
/***************************************/
|
101
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
102
|
+
/***************************************/
|
103
|
+
|
104
|
+
static void QueueObjectMatchAction(Environment *,int,Instance *,int);
|
105
|
+
static SLOT_BITMAP *QueueModifySlotMap(Environment *,SLOT_BITMAP *,int);
|
106
|
+
static void ReturnObjectMatchAction(Environment *,OBJECT_MATCH_ACTION *);
|
107
|
+
static void ProcessObjectMatchQueue(Environment *);
|
108
|
+
static void MarkObjectPatternNetwork(Environment *,SLOT_BITMAP *);
|
109
|
+
static bool CompareSlotBitMaps(const SLOT_BITMAP *,const SLOT_BITMAP *);
|
110
|
+
static void ObjectPatternMatch(Environment *,size_t,size_t,OBJECT_PATTERN_NODE *,struct multifieldMarker *);
|
111
|
+
static void ProcessPatternNode(Environment *,size_t,size_t,OBJECT_PATTERN_NODE *,struct multifieldMarker *);
|
112
|
+
static void CreateObjectAlphaMatch(Environment *,OBJECT_ALPHA_NODE *);
|
113
|
+
static bool EvaluateObjectPatternTest(Environment *,size_t,struct multifieldMarker *,
|
114
|
+
Expression *,OBJECT_PATTERN_NODE *);
|
115
|
+
static void ObjectAssertAction(Environment *,Instance *);
|
116
|
+
static void ObjectModifyAction(Environment *,Instance *,SLOT_BITMAP *);
|
117
|
+
static void ObjectRetractAction(Environment *,Instance *,SLOT_BITMAP *);
|
118
|
+
static void ObjectPatternNetErrorMessage(Environment *,OBJECT_PATTERN_NODE *);
|
119
|
+
static void TraceErrorToObjectPattern(Environment *,bool,OBJECT_PATTERN_NODE *);
|
120
|
+
|
121
|
+
/* =========================================
|
122
|
+
*****************************************
|
123
|
+
EXTERNALLY VISIBLE FUNCTIONS
|
124
|
+
=========================================
|
125
|
+
***************************************** */
|
126
|
+
|
127
|
+
/***************************************************************************
|
128
|
+
NAME : ObjectMatchDelay
|
129
|
+
DESCRIPTION : H/L interface for SetDelayObjectPatternMatching
|
130
|
+
INPUTS : None
|
131
|
+
RETURNS : Nothing useful
|
132
|
+
SIDE EFFECTS : DelayObjectPatternMatching set and Rete network updates
|
133
|
+
delayed until pattern-matching is completed
|
134
|
+
NOTES : H/L Syntax: (object-pattern-match-delay <action>*)
|
135
|
+
***************************************************************************/
|
136
|
+
void ObjectMatchDelay(
|
137
|
+
Environment *theEnv,
|
138
|
+
UDFContext *context,
|
139
|
+
UDFValue *returnValue)
|
140
|
+
{
|
141
|
+
bool ov;
|
142
|
+
|
143
|
+
ov = SetDelayObjectPatternMatching(theEnv,true);
|
144
|
+
|
145
|
+
if (! UDFFirstArgument(context,ANY_TYPE_BITS,returnValue))
|
146
|
+
{ return; }
|
147
|
+
|
148
|
+
if (EvaluationData(theEnv)->EvaluationError)
|
149
|
+
{
|
150
|
+
SetHaltExecution(theEnv,false);
|
151
|
+
SetEvaluationError(theEnv,false);
|
152
|
+
SetDelayObjectPatternMatching(theEnv,ov);
|
153
|
+
SetEvaluationError(theEnv,true);
|
154
|
+
}
|
155
|
+
else
|
156
|
+
SetDelayObjectPatternMatching(theEnv,ov);
|
157
|
+
}
|
158
|
+
|
159
|
+
/***************************************************
|
160
|
+
NAME : SetDelayObjectPatternMatching
|
161
|
+
DESCRIPTION : Sets the flag determining if Rete
|
162
|
+
network activity is to be delayed
|
163
|
+
for objects or not
|
164
|
+
INPUTS : The value of the flag
|
165
|
+
RETURNS : The old value of the flag
|
166
|
+
SIDE EFFECTS : DelayObjectPatternMatching set
|
167
|
+
NOTES : When the delay is set to false,
|
168
|
+
all pending Rete network updates
|
169
|
+
are performed
|
170
|
+
***************************************************/
|
171
|
+
bool SetDelayObjectPatternMatching(
|
172
|
+
Environment *theEnv,
|
173
|
+
bool value)
|
174
|
+
{
|
175
|
+
bool oldval;
|
176
|
+
|
177
|
+
oldval = ObjectReteData(theEnv)->DelayObjectPatternMatching;
|
178
|
+
if (value)
|
179
|
+
ObjectReteData(theEnv)->DelayObjectPatternMatching = true;
|
180
|
+
else
|
181
|
+
{
|
182
|
+
ObjectReteData(theEnv)->DelayObjectPatternMatching = false;
|
183
|
+
ObjectNetworkAction(theEnv,0,NULL,-1);
|
184
|
+
}
|
185
|
+
return(oldval);
|
186
|
+
}
|
187
|
+
|
188
|
+
/***************************************************
|
189
|
+
NAME : GetDelayObjectPatternMatching
|
190
|
+
DESCRIPTION : Gets the flag determining if Rete
|
191
|
+
network activity is to be delayed
|
192
|
+
for objects or not
|
193
|
+
INPUTS : None
|
194
|
+
RETURNS : The flag
|
195
|
+
SIDE EFFECTS : None
|
196
|
+
NOTES : None
|
197
|
+
***************************************************/
|
198
|
+
bool GetDelayObjectPatternMatching(
|
199
|
+
Environment *theEnv)
|
200
|
+
{
|
201
|
+
return(ObjectReteData(theEnv)->DelayObjectPatternMatching);
|
202
|
+
}
|
203
|
+
|
204
|
+
/********************************************************
|
205
|
+
NAME : ObjectNetworkPointer
|
206
|
+
DESCRIPTION : Returns the first object network
|
207
|
+
pattern node
|
208
|
+
INPUTS : None
|
209
|
+
RETURNS : The top of the object pattern network
|
210
|
+
SIDE EFFECTS : None
|
211
|
+
NOTES : None
|
212
|
+
********************************************************/
|
213
|
+
OBJECT_PATTERN_NODE *ObjectNetworkPointer(
|
214
|
+
Environment *theEnv)
|
215
|
+
{
|
216
|
+
return(ObjectReteData(theEnv)->ObjectPatternNetworkPointer);
|
217
|
+
}
|
218
|
+
|
219
|
+
/********************************************************
|
220
|
+
NAME : ObjectNetworkTerminalPointer
|
221
|
+
DESCRIPTION : Returns the first terminal pattern node
|
222
|
+
INPUTS : None
|
223
|
+
RETURNS : The last node of a pattern
|
224
|
+
SIDE EFFECTS : None
|
225
|
+
NOTES : None
|
226
|
+
********************************************************/
|
227
|
+
OBJECT_ALPHA_NODE *ObjectNetworkTerminalPointer(
|
228
|
+
Environment *theEnv)
|
229
|
+
{
|
230
|
+
return(ObjectReteData(theEnv)->ObjectPatternNetworkTerminalPointer);
|
231
|
+
}
|
232
|
+
|
233
|
+
/***************************************************
|
234
|
+
NAME : SetObjectNetworkPointer
|
235
|
+
DESCRIPTION : Sets the object pattern network to
|
236
|
+
the given network
|
237
|
+
INPUTS : Top of the new pattern network
|
238
|
+
RETURNS : Nothing useful
|
239
|
+
SIDE EFFECTS : ObjectPatternNetworkPointer set
|
240
|
+
NOTES : None
|
241
|
+
***************************************************/
|
242
|
+
void SetObjectNetworkPointer(
|
243
|
+
Environment *theEnv,
|
244
|
+
OBJECT_PATTERN_NODE *value)
|
245
|
+
{
|
246
|
+
ObjectReteData(theEnv)->ObjectPatternNetworkPointer = value;
|
247
|
+
}
|
248
|
+
|
249
|
+
/*******************************************************
|
250
|
+
NAME : SetObjectNetworkTerminalPointer
|
251
|
+
DESCRIPTION : Sets the global list of terminal
|
252
|
+
pattern nodes (the ones containing
|
253
|
+
the bitmaps) to the given node
|
254
|
+
INPUTS : The last node of a pattern
|
255
|
+
RETURNS : Nothing useful
|
256
|
+
SIDE EFFECTS : ObjectPatternNetworkTerminalPointer set
|
257
|
+
NOTES : None
|
258
|
+
*******************************************************/
|
259
|
+
void SetObjectNetworkTerminalPointer(
|
260
|
+
Environment *theEnv,
|
261
|
+
OBJECT_ALPHA_NODE *value)
|
262
|
+
{
|
263
|
+
ObjectReteData(theEnv)->ObjectPatternNetworkTerminalPointer = value;
|
264
|
+
}
|
265
|
+
|
266
|
+
/************************************************************************
|
267
|
+
NAME : ObjectNetworkAction
|
268
|
+
DESCRIPTION : Main driver for pattern-matching on objects
|
269
|
+
If the pattern-matching is current delayed or another
|
270
|
+
object is currently being pattern-matched, the requested
|
271
|
+
match action is queued for later processing.
|
272
|
+
Otherwise, the match action is performed and the
|
273
|
+
Rete network is updated.
|
274
|
+
INPUTS : 1) The match action type
|
275
|
+
OBJECT_ASSERT (1)
|
276
|
+
OBJECT_RETRACT (2)
|
277
|
+
OBJECT_MODIFY (3)
|
278
|
+
2) The instance to be matched (can be NULL if only
|
279
|
+
want pending actions to be performed)
|
280
|
+
3) The name id of the slot being updated (can be -1)
|
281
|
+
If this argument is -1, it is assumed that any
|
282
|
+
pattern which could match this instance must be
|
283
|
+
checked. Otherwise, only the patterns which
|
284
|
+
explicitly match on the named slot will be checked.
|
285
|
+
RETURNS : Nothing useful
|
286
|
+
SIDE EFFECTS : Action queued or Rete network updated
|
287
|
+
NOTES : None
|
288
|
+
************************************************************************/
|
289
|
+
void ObjectNetworkAction(
|
290
|
+
Environment *theEnv,
|
291
|
+
int type,
|
292
|
+
Instance *ins,
|
293
|
+
int slotNameID)
|
294
|
+
{
|
295
|
+
SLOT_BITMAP *tmpMap;
|
296
|
+
|
297
|
+
if (EngineData(theEnv)->JoinOperationInProgress)
|
298
|
+
return;
|
299
|
+
|
300
|
+
EngineData(theEnv)->JoinOperationInProgress = true;
|
301
|
+
|
302
|
+
|
303
|
+
/* ================================================
|
304
|
+
For purposes of conflict resolution, all objects
|
305
|
+
which have had pattern-matching delayed will
|
306
|
+
have the same relative timestamp, i.e., the
|
307
|
+
inference engine thinks they all just appeared
|
308
|
+
simultaneously
|
309
|
+
|
310
|
+
When delay is off, however, each object gets the
|
311
|
+
new and current timestamp as expected.
|
312
|
+
================================================ */
|
313
|
+
ObjectReteData(theEnv)->UseEntityTimeTag = DefruleData(theEnv)->CurrentEntityTimeTag++;
|
314
|
+
|
315
|
+
/* ==================================================
|
316
|
+
If pattern-matching is delayed (by use of the
|
317
|
+
set-object-pattern-match-delay function), then
|
318
|
+
the instance should be marked for later processing
|
319
|
+
(when the delay is turned off).
|
320
|
+
================================================== */
|
321
|
+
if (ins != NULL)
|
322
|
+
{
|
323
|
+
/* 6.05 Bug Fix */
|
324
|
+
ins->reteSynchronized = false;
|
325
|
+
|
326
|
+
if (ObjectReteData(theEnv)->DelayObjectPatternMatching == false)
|
327
|
+
switch (type)
|
328
|
+
{
|
329
|
+
case OBJECT_ASSERT :
|
330
|
+
ObjectAssertAction(theEnv,ins);
|
331
|
+
break;
|
332
|
+
case OBJECT_RETRACT :
|
333
|
+
ObjectRetractAction(theEnv,ins,NULL);
|
334
|
+
break;
|
335
|
+
default :
|
336
|
+
tmpMap = QueueModifySlotMap(theEnv,NULL,slotNameID);
|
337
|
+
ObjectModifyAction(theEnv,ins,tmpMap);
|
338
|
+
rm(theEnv,tmpMap,SlotBitMapSize(tmpMap));
|
339
|
+
}
|
340
|
+
else
|
341
|
+
QueueObjectMatchAction(theEnv,type,ins,slotNameID);
|
342
|
+
}
|
343
|
+
|
344
|
+
/* ========================================
|
345
|
+
Process all pending actions in the queue
|
346
|
+
All updates will use the same timestamp
|
347
|
+
======================================== */
|
348
|
+
ProcessObjectMatchQueue(theEnv);
|
349
|
+
|
350
|
+
EngineData(theEnv)->JoinOperationInProgress = false;
|
351
|
+
|
352
|
+
ForceLogicalRetractions(theEnv);
|
353
|
+
|
354
|
+
/*=========================================*/
|
355
|
+
/* Free partial matches that were released */
|
356
|
+
/* by the assertion of the fact. */
|
357
|
+
/*=========================================*/
|
358
|
+
|
359
|
+
if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
|
360
|
+
}
|
361
|
+
|
362
|
+
/* =========================================
|
363
|
+
*****************************************
|
364
|
+
INTERNALLY VISIBLE FUNCTIONS
|
365
|
+
=========================================
|
366
|
+
***************************************** */
|
367
|
+
|
368
|
+
/***************************************************
|
369
|
+
NAME : ResetObjectMatchTimeTags
|
370
|
+
DESCRIPTION : If CurrentObjectMatchTimeTag + 1
|
371
|
+
would cause an overflow,
|
372
|
+
CurrentObjectMatchTimeTag
|
373
|
+
is reset to 0L and all time tags
|
374
|
+
in object pattern nodes are reset.
|
375
|
+
INPUTS : None
|
376
|
+
RETURNS : Nothing useful
|
377
|
+
SIDE EFFECTS : CurrentObjectMatchTimeTag reset to
|
378
|
+
0, and all match time tags reset
|
379
|
+
These tags are used to recognize
|
380
|
+
valid pattern nodes on a match
|
381
|
+
NOTES : None
|
382
|
+
***************************************************/
|
383
|
+
void ResetObjectMatchTimeTags(
|
384
|
+
Environment *theEnv)
|
385
|
+
{
|
386
|
+
OBJECT_ALPHA_NODE *alphaPtr;
|
387
|
+
OBJECT_PATTERN_NODE *lastLevel;
|
388
|
+
|
389
|
+
/* ============================================
|
390
|
+
If the current tag incremented by one would
|
391
|
+
not cause an overflow, then we can leave
|
392
|
+
things alone.
|
393
|
+
============================================ */
|
394
|
+
if ((ObjectReteData(theEnv)->CurrentObjectMatchTimeTag + 1L) > ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
|
395
|
+
return;
|
396
|
+
ObjectReteData(theEnv)->CurrentObjectMatchTimeTag = 0L;
|
397
|
+
alphaPtr = ObjectNetworkTerminalPointer(theEnv);
|
398
|
+
while (alphaPtr != NULL)
|
399
|
+
{
|
400
|
+
alphaPtr->matchTimeTag = 0L;
|
401
|
+
lastLevel = alphaPtr->patternNode;
|
402
|
+
while (lastLevel != NULL)
|
403
|
+
{
|
404
|
+
if (lastLevel->matchTimeTag == 0L)
|
405
|
+
break;
|
406
|
+
lastLevel->matchTimeTag = 0L;
|
407
|
+
lastLevel = lastLevel->lastLevel;
|
408
|
+
}
|
409
|
+
alphaPtr = alphaPtr->nxtTerminal;
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
413
|
+
/***************************************************
|
414
|
+
NAME : QueueObjectMatchAction
|
415
|
+
DESCRIPTION : Posts a Rete network match event
|
416
|
+
for later processing
|
417
|
+
INPUTS : 1) The match action type
|
418
|
+
OBJECT_ASSERT (1)
|
419
|
+
OBJECT_RETRACT (2)
|
420
|
+
OBJECT_MODIFY (3)
|
421
|
+
2) The instance to be matched
|
422
|
+
3) The name id of the slot being
|
423
|
+
updated (can be -1)
|
424
|
+
RETURNS : Nothing useful
|
425
|
+
SIDE EFFECTS : Queue updated
|
426
|
+
NOTES : None
|
427
|
+
***************************************************/
|
428
|
+
static void QueueObjectMatchAction(
|
429
|
+
Environment *theEnv,
|
430
|
+
int type,
|
431
|
+
Instance *ins,
|
432
|
+
int slotNameID)
|
433
|
+
{
|
434
|
+
OBJECT_MATCH_ACTION *prv,*cur,*newMatch;
|
435
|
+
OBJECT_MATCH_ACTION *prvRetract = NULL; /* DR0873 */
|
436
|
+
|
437
|
+
prv = NULL;
|
438
|
+
cur = ObjectReteData(theEnv)->ObjectMatchActionQueue;
|
439
|
+
while (cur != NULL)
|
440
|
+
{
|
441
|
+
/* ===========================================================
|
442
|
+
Here are the possibilities for the first Rete event already
|
443
|
+
on the queue as compared with the new event for an object:
|
444
|
+
|
445
|
+
Assert/Retract --> Delete assert event
|
446
|
+
Ignore retract event
|
447
|
+
Assert/Modify --> Ignore modify event
|
448
|
+
Modify/Modify --> Merge new modify event
|
449
|
+
Modify/Retract --> Delete modify event
|
450
|
+
Queue the retract event
|
451
|
+
=========================================================== */
|
452
|
+
if (cur->ins == ins)
|
453
|
+
{
|
454
|
+
/* ===================================================
|
455
|
+
An action for initially asserting the newly created
|
456
|
+
object to all applicable patterns
|
457
|
+
=================================================== */
|
458
|
+
if (cur->type == OBJECT_ASSERT)
|
459
|
+
{
|
460
|
+
if (type == OBJECT_RETRACT)
|
461
|
+
{
|
462
|
+
/* ===================================================
|
463
|
+
If we are retracting the entire object, then we can
|
464
|
+
remove the assert action (and all modifies as well)
|
465
|
+
and ignore the retract action
|
466
|
+
(basically the object came and went before the Rete
|
467
|
+
network had a chance to see it)
|
468
|
+
=================================================== */
|
469
|
+
if (prv == NULL)
|
470
|
+
ObjectReteData(theEnv)->ObjectMatchActionQueue = cur->nxt;
|
471
|
+
else
|
472
|
+
prv->nxt = cur->nxt;
|
473
|
+
cur->ins->busy--;
|
474
|
+
ReturnObjectMatchAction(theEnv,cur);
|
475
|
+
}
|
476
|
+
|
477
|
+
/* =================================================
|
478
|
+
If this is a modify action, then we can ignore it
|
479
|
+
since the assert action will encompass it
|
480
|
+
================================================= */
|
481
|
+
}
|
482
|
+
|
483
|
+
/* ===================================================
|
484
|
+
If the object is being deleted after a slot modify,
|
485
|
+
drop the modify event and replace with the retract
|
486
|
+
=================================================== */
|
487
|
+
else if (type == OBJECT_RETRACT)
|
488
|
+
{
|
489
|
+
cur->type = OBJECT_RETRACT;
|
490
|
+
if (cur->slotNameIDs != NULL)
|
491
|
+
{
|
492
|
+
rm(theEnv,cur->slotNameIDs,SlotBitMapSize(cur->slotNameIDs));
|
493
|
+
cur->slotNameIDs = NULL;
|
494
|
+
}
|
495
|
+
}
|
496
|
+
|
497
|
+
/* ====================================================
|
498
|
+
If a modify event for this slot is already on the
|
499
|
+
queue, ignore this one. Otherwise, merge the slot id
|
500
|
+
==================================================== */
|
501
|
+
else
|
502
|
+
cur->slotNameIDs = QueueModifySlotMap(theEnv,cur->slotNameIDs,slotNameID);
|
503
|
+
|
504
|
+
return;
|
505
|
+
}
|
506
|
+
|
507
|
+
if (cur->type == OBJECT_RETRACT) /* DR0873 */
|
508
|
+
{ prvRetract = cur; } /* DR0873 */
|
509
|
+
prv = cur;
|
510
|
+
cur = cur->nxt;
|
511
|
+
}
|
512
|
+
|
513
|
+
/* ================================================
|
514
|
+
If there are no actions for the instance already
|
515
|
+
on the queue, the new action is simply appended.
|
516
|
+
================================================ */
|
517
|
+
newMatch = get_struct(theEnv,objectMatchAction);
|
518
|
+
newMatch->type = type;
|
519
|
+
newMatch->nxt = NULL; /* If we get here, cur should be NULL */
|
520
|
+
newMatch->slotNameIDs = (type != OBJECT_MODIFY) ? NULL :
|
521
|
+
QueueModifySlotMap(theEnv,NULL,slotNameID);
|
522
|
+
newMatch->ins = ins;
|
523
|
+
newMatch->ins->busy++;
|
524
|
+
|
525
|
+
/* DR0873 Begin */
|
526
|
+
/* Retract operations must be processed before assert and */
|
527
|
+
/* modify actions, otherwise the pattern matching process */
|
528
|
+
/* might attempt to access the slots of a retract instance. */
|
529
|
+
|
530
|
+
if (type == OBJECT_RETRACT)
|
531
|
+
{
|
532
|
+
if (prvRetract == NULL)
|
533
|
+
{
|
534
|
+
newMatch->nxt = ObjectReteData(theEnv)->ObjectMatchActionQueue;
|
535
|
+
ObjectReteData(theEnv)->ObjectMatchActionQueue = newMatch;
|
536
|
+
}
|
537
|
+
else
|
538
|
+
{
|
539
|
+
newMatch->nxt = prvRetract->nxt;
|
540
|
+
prvRetract->nxt = newMatch;
|
541
|
+
}
|
542
|
+
}
|
543
|
+
else
|
544
|
+
/* DR0873 End */
|
545
|
+
|
546
|
+
if (prv == NULL)
|
547
|
+
ObjectReteData(theEnv)->ObjectMatchActionQueue = newMatch;
|
548
|
+
else
|
549
|
+
prv->nxt = newMatch;
|
550
|
+
}
|
551
|
+
|
552
|
+
/****************************************************
|
553
|
+
NAME : QueueModifySlotMap
|
554
|
+
DESCRIPTION : Sets the bitmap for a queued
|
555
|
+
object modify Rete network action
|
556
|
+
INPUTS : 1) The old bitmap (can be NULL)
|
557
|
+
2) The canonical slot id to set
|
558
|
+
RETURNS : The (new) bitmap
|
559
|
+
SIDE EFFECTS : Bitmap allocated/reallocated if
|
560
|
+
necessary, and slot id bit set
|
561
|
+
NOTES : If the bitmap must be (re)allocated,
|
562
|
+
this routine allocates twice the
|
563
|
+
room necessary for the current id
|
564
|
+
to allow for growth.
|
565
|
+
****************************************************/
|
566
|
+
static SLOT_BITMAP *QueueModifySlotMap(
|
567
|
+
Environment *theEnv,
|
568
|
+
SLOT_BITMAP *oldMap,
|
569
|
+
int slotNameID)
|
570
|
+
{
|
571
|
+
SLOT_BITMAP *newMap;
|
572
|
+
unsigned short newmaxid;
|
573
|
+
unsigned oldsz,newsz;
|
574
|
+
|
575
|
+
if ((oldMap == NULL) ? true : (slotNameID > oldMap->maxid))
|
576
|
+
{
|
577
|
+
newmaxid = (unsigned short) (slotNameID * 2);
|
578
|
+
newsz = sizeof(SLOT_BITMAP) +
|
579
|
+
(sizeof(char) * (newmaxid / BITS_PER_BYTE));
|
580
|
+
newMap = (SLOT_BITMAP *) gm2(theEnv,newsz);
|
581
|
+
ClearBitString(newMap,newsz);
|
582
|
+
if (oldMap != NULL)
|
583
|
+
{
|
584
|
+
oldsz = SlotBitMapSize(oldMap);
|
585
|
+
GenCopyMemory(char,oldsz,newMap,oldMap);
|
586
|
+
rm(theEnv,oldMap,oldsz);
|
587
|
+
}
|
588
|
+
newMap->maxid = newmaxid;
|
589
|
+
}
|
590
|
+
else
|
591
|
+
newMap = oldMap;
|
592
|
+
SetBitMap(newMap->map,slotNameID);
|
593
|
+
return(newMap);
|
594
|
+
}
|
595
|
+
|
596
|
+
/***************************************************
|
597
|
+
NAME : ReturnObjectMatchAction
|
598
|
+
DESCRIPTION : Deallocates and object match action
|
599
|
+
structure and associated slot
|
600
|
+
bitmap (if any)
|
601
|
+
INPUTS : The queued match action item
|
602
|
+
RETURNS : Nothing useful
|
603
|
+
SIDE EFFECTS : Object match action item deleted
|
604
|
+
NOTES : None
|
605
|
+
***************************************************/
|
606
|
+
static void ReturnObjectMatchAction(
|
607
|
+
Environment *theEnv,
|
608
|
+
OBJECT_MATCH_ACTION *omaPtr)
|
609
|
+
{
|
610
|
+
if (omaPtr->slotNameIDs != NULL)
|
611
|
+
rm(theEnv,omaPtr->slotNameIDs,SlotBitMapSize(omaPtr->slotNameIDs));
|
612
|
+
rtn_struct(theEnv,objectMatchAction,omaPtr);
|
613
|
+
}
|
614
|
+
|
615
|
+
/***************************************************
|
616
|
+
NAME : ProcessObjectMatchQueue
|
617
|
+
DESCRIPTION : Processes all outstanding object
|
618
|
+
Rete network update events
|
619
|
+
INPUTS : None
|
620
|
+
RETURNS : Nothing useful
|
621
|
+
SIDE EFFECTS : Pattern-matching on objects
|
622
|
+
NOTES : None
|
623
|
+
***************************************************/
|
624
|
+
static void ProcessObjectMatchQueue(
|
625
|
+
Environment *theEnv)
|
626
|
+
{
|
627
|
+
OBJECT_MATCH_ACTION *cur;
|
628
|
+
|
629
|
+
while ((ObjectReteData(theEnv)->ObjectMatchActionQueue != NULL) &&
|
630
|
+
(ObjectReteData(theEnv)->DelayObjectPatternMatching == false))
|
631
|
+
{
|
632
|
+
cur = ObjectReteData(theEnv)->ObjectMatchActionQueue;
|
633
|
+
ObjectReteData(theEnv)->ObjectMatchActionQueue = cur->nxt;
|
634
|
+
|
635
|
+
switch(cur->type)
|
636
|
+
{
|
637
|
+
case OBJECT_ASSERT :
|
638
|
+
ObjectAssertAction(theEnv,cur->ins);
|
639
|
+
break;
|
640
|
+
case OBJECT_RETRACT :
|
641
|
+
ObjectRetractAction(theEnv,cur->ins,cur->slotNameIDs);
|
642
|
+
break;
|
643
|
+
default :
|
644
|
+
ObjectModifyAction(theEnv,cur->ins,cur->slotNameIDs);
|
645
|
+
}
|
646
|
+
cur->ins->busy--;
|
647
|
+
ReturnObjectMatchAction(theEnv,cur);
|
648
|
+
}
|
649
|
+
}
|
650
|
+
|
651
|
+
/******************************************************
|
652
|
+
NAME : MarkObjectPatternNetwork
|
653
|
+
DESCRIPTION : Iterates through all terminal
|
654
|
+
pattern nodes checking class and
|
655
|
+
slot bitmaps. If a pattern is
|
656
|
+
applicable to the object/slot change,
|
657
|
+
then all the nodes belonging to
|
658
|
+
the pattern are marked as needing
|
659
|
+
to be examined by the pattern matcher.
|
660
|
+
INPUTS : The bitmap of ids of the slots being
|
661
|
+
changed (NULL if this is an assert for the
|
662
|
+
for the entire object)
|
663
|
+
RETURNS : Nothing useful
|
664
|
+
SIDE EFFECTS : Applicable pattern nodes marked
|
665
|
+
NOTES : Incremental reset status is also
|
666
|
+
checked here
|
667
|
+
******************************************************/
|
668
|
+
static void MarkObjectPatternNetwork(
|
669
|
+
Environment *theEnv,
|
670
|
+
SLOT_BITMAP *slotNameIDs)
|
671
|
+
{
|
672
|
+
OBJECT_ALPHA_NODE *alphaPtr;
|
673
|
+
OBJECT_PATTERN_NODE *upper;
|
674
|
+
Defclass *cls;
|
675
|
+
CLASS_ALPHA_LINK *current_alpha_link;
|
676
|
+
|
677
|
+
cls = ObjectReteData(theEnv)->CurrentPatternObject->cls;
|
678
|
+
current_alpha_link = cls->relevant_terminal_alpha_nodes;
|
679
|
+
|
680
|
+
ResetObjectMatchTimeTags(theEnv);
|
681
|
+
ObjectReteData(theEnv)->CurrentObjectMatchTimeTag++;
|
682
|
+
|
683
|
+
while (current_alpha_link != NULL)
|
684
|
+
{
|
685
|
+
alphaPtr = current_alpha_link->alphaNode;
|
686
|
+
|
687
|
+
/* =============================================================
|
688
|
+
If an incremental reset is in progress, make sure that the
|
689
|
+
pattern has been marked for initialization before proceeding.
|
690
|
+
============================================================= */
|
691
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
692
|
+
if (EngineData(theEnv)->IncrementalResetInProgress &&
|
693
|
+
(alphaPtr->header.initialize == false))
|
694
|
+
{
|
695
|
+
current_alpha_link = current_alpha_link->next;
|
696
|
+
continue;
|
697
|
+
}
|
698
|
+
#endif
|
699
|
+
|
700
|
+
/* ===================================================
|
701
|
+
If we are doing an assert, then we need to
|
702
|
+
check all patterns which satsify the class bitmap
|
703
|
+
(The retraction has already been done in this case)
|
704
|
+
=================================================== */
|
705
|
+
if (slotNameIDs == NULL)
|
706
|
+
{
|
707
|
+
alphaPtr->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag;
|
708
|
+
|
709
|
+
for (upper = alphaPtr->patternNode;
|
710
|
+
upper != NULL;
|
711
|
+
upper = upper->lastLevel)
|
712
|
+
{
|
713
|
+
if (upper->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
|
714
|
+
{ break; }
|
715
|
+
else
|
716
|
+
{ upper->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag; }
|
717
|
+
}
|
718
|
+
}
|
719
|
+
|
720
|
+
/* ===================================================
|
721
|
+
If we are doing a slot modify, then we need to
|
722
|
+
check only the subset of patterns which satisfy the
|
723
|
+
class bitmap AND actually match on the slot in
|
724
|
+
question.
|
725
|
+
=================================================== */
|
726
|
+
else if (alphaPtr->slotbmp != NULL)
|
727
|
+
{
|
728
|
+
if (CompareSlotBitMaps(slotNameIDs,
|
729
|
+
(const SLOT_BITMAP *) alphaPtr->slotbmp->contents))
|
730
|
+
{
|
731
|
+
alphaPtr->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag;
|
732
|
+
for (upper = alphaPtr->patternNode;
|
733
|
+
upper != NULL;
|
734
|
+
upper = upper->lastLevel)
|
735
|
+
{
|
736
|
+
if (upper->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
|
737
|
+
{ break; }
|
738
|
+
else
|
739
|
+
{ upper->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag; }
|
740
|
+
}
|
741
|
+
}
|
742
|
+
}
|
743
|
+
|
744
|
+
current_alpha_link = current_alpha_link->next;
|
745
|
+
}
|
746
|
+
}
|
747
|
+
|
748
|
+
/***************************************************
|
749
|
+
NAME : CompareSlotBitMaps
|
750
|
+
DESCRIPTION : Compares two slot bitmaps by
|
751
|
+
bitwising and'ing byte per byte up
|
752
|
+
to the length of the smaller map.
|
753
|
+
INPUTS : The two slot bitmaps
|
754
|
+
RETURNS : True if any common bits
|
755
|
+
are set in both maps, false
|
756
|
+
otherwise
|
757
|
+
SIDE EFFECTS : None
|
758
|
+
NOTES : None
|
759
|
+
***************************************************/
|
760
|
+
static bool CompareSlotBitMaps(
|
761
|
+
const SLOT_BITMAP *smap1,
|
762
|
+
const SLOT_BITMAP *smap2)
|
763
|
+
{
|
764
|
+
unsigned short i, maxByte;
|
765
|
+
|
766
|
+
maxByte = (unsigned short)
|
767
|
+
(((smap1->maxid < smap2->maxid) ?
|
768
|
+
smap1->maxid : smap2->maxid) / BITS_PER_BYTE);
|
769
|
+
for (i = 0 ; i <= maxByte ; i++)
|
770
|
+
if (smap1->map[i] & smap2->map[i])
|
771
|
+
return true;
|
772
|
+
return false;
|
773
|
+
}
|
774
|
+
|
775
|
+
/**********************************************************************************
|
776
|
+
NAME : ObjectPatternMatch
|
777
|
+
DESCRIPTION : Iterates through all the pattern nodes on one level
|
778
|
+
in the pattern network. A node is only processed
|
779
|
+
if it can lead to a terminating class bitmap node
|
780
|
+
which applies to the object being matched. This
|
781
|
+
allows for a significant reduction in the number of
|
782
|
+
patterns considered.
|
783
|
+
INPUTS : 1) The offset of the slot position from the pattern index
|
784
|
+
2) The pattern node being examined
|
785
|
+
3) The end of the list of multifield markers for the pattern
|
786
|
+
RETURNS : Nothing useful
|
787
|
+
SIDE EFFECTS : The pattern tests are evaluated and the child nodes may
|
788
|
+
be processed (which may cause a whole series of Rete network
|
789
|
+
updates).
|
790
|
+
NOTES : Several globals are used to keep track of the current
|
791
|
+
slot being examined:
|
792
|
+
CurrentPatternMarks - the series of multifield markers
|
793
|
+
CurrentPatternObject - the object being pattern-matched
|
794
|
+
CurrentPatternObjectSlot - the current slot being examined
|
795
|
+
CurrentObjectSlotLength - the cardinality of the slot value
|
796
|
+
|
797
|
+
An optimization is performed when evaluating
|
798
|
+
constant tests on a slot value field. All
|
799
|
+
pattern nodes on a level which restrict the same slot
|
800
|
+
are grouped together. Those which are constant
|
801
|
+
tests are placed at the far right. Thus, as soon
|
802
|
+
as one of these constant tests succeeds, the remaining
|
803
|
+
nodes for that slot on this level can be skipped
|
804
|
+
**********************************************************************************/
|
805
|
+
static void ObjectPatternMatch(
|
806
|
+
Environment *theEnv,
|
807
|
+
size_t offset,
|
808
|
+
size_t multifieldsProcessed,
|
809
|
+
OBJECT_PATTERN_NODE *patternTop,
|
810
|
+
struct multifieldMarker *endMark)
|
811
|
+
{
|
812
|
+
size_t saveSlotLength;
|
813
|
+
InstanceSlot *saveSlot;
|
814
|
+
OBJECT_PATTERN_NODE *blockedNode;
|
815
|
+
|
816
|
+
while (patternTop != NULL)
|
817
|
+
{
|
818
|
+
/*=============================================================*/
|
819
|
+
/* MarkObjectPatternNetwork() has already marked pattern nodes */
|
820
|
+
/* which need processing according to the class bitmaps, slot */
|
821
|
+
/* updates and incremental reset status. */
|
822
|
+
/*=============================================================*/
|
823
|
+
|
824
|
+
if (patternTop->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
|
825
|
+
{
|
826
|
+
/*===========================================*/
|
827
|
+
/* Make sure we are examining the correct */
|
828
|
+
/* slot of the object for this pattern node. */
|
829
|
+
/*===========================================*/
|
830
|
+
|
831
|
+
if ((patternTop->slotNameID == ISA_ID) ||
|
832
|
+
(patternTop->slotNameID == NAME_ID))
|
833
|
+
{
|
834
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
|
835
|
+
ObjectReteData(theEnv)->CurrentObjectSlotLength = 1;
|
836
|
+
offset = 0;
|
837
|
+
}
|
838
|
+
else if ((ObjectReteData(theEnv)->CurrentPatternObjectSlot == NULL) ? true :
|
839
|
+
(ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->slotName->id != patternTop->slotNameID))
|
840
|
+
{
|
841
|
+
/*=======================================================*/
|
842
|
+
/* Need to reset the indices for the multifield */
|
843
|
+
/* markers now that we have moved onto a different slot. */
|
844
|
+
/*=======================================================*/
|
845
|
+
|
846
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot =
|
847
|
+
ObjectReteData(theEnv)->CurrentPatternObject->slotAddresses[ObjectReteData(theEnv)->CurrentPatternObject->cls->slotNameMap
|
848
|
+
[patternTop->slotNameID] - 1];
|
849
|
+
offset = 0;
|
850
|
+
if (ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->multiple)
|
851
|
+
ObjectReteData(theEnv)->CurrentObjectSlotLength =
|
852
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot->multifieldValue->length;
|
853
|
+
else
|
854
|
+
ObjectReteData(theEnv)->CurrentObjectSlotLength = 1;
|
855
|
+
}
|
856
|
+
|
857
|
+
/*==========================================================*/
|
858
|
+
/* Process the pattern node. If it is satisfied by the */
|
859
|
+
/* the instance, ProcessPatternNode() will recursively pass */
|
860
|
+
/* all of its children nodes through ObjectPatternMatch(). */
|
861
|
+
/*==========================================================*/
|
862
|
+
|
863
|
+
saveSlotLength = ObjectReteData(theEnv)->CurrentObjectSlotLength;
|
864
|
+
saveSlot = ObjectReteData(theEnv)->CurrentPatternObjectSlot;
|
865
|
+
ProcessPatternNode(theEnv,offset,multifieldsProcessed,patternTop,endMark);
|
866
|
+
ObjectReteData(theEnv)->CurrentObjectSlotLength = saveSlotLength;
|
867
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot = saveSlot;
|
868
|
+
}
|
869
|
+
|
870
|
+
/*============================================================*/
|
871
|
+
/* Move on to the siblings of this node - if the current node */
|
872
|
+
/* was a constant test that succeeded, skip further sibling */
|
873
|
+
/* nodes (which test on the same field in the pattern) which */
|
874
|
+
/* match on the same slot since they are all constant tests */
|
875
|
+
/* as well and will, of course fail. */
|
876
|
+
/*============================================================*/
|
877
|
+
|
878
|
+
if (patternTop->blocked == true)
|
879
|
+
{
|
880
|
+
patternTop->blocked = false;
|
881
|
+
blockedNode = patternTop;
|
882
|
+
patternTop = patternTop->rightNode;
|
883
|
+
while (patternTop != NULL)
|
884
|
+
{
|
885
|
+
if ((patternTop->slotNameID != blockedNode->slotNameID) ||
|
886
|
+
(patternTop->whichField != blockedNode->whichField))
|
887
|
+
break;
|
888
|
+
patternTop = patternTop->rightNode;
|
889
|
+
}
|
890
|
+
}
|
891
|
+
else
|
892
|
+
patternTop = patternTop->rightNode;
|
893
|
+
}
|
894
|
+
}
|
895
|
+
|
896
|
+
/**********************************************************************************
|
897
|
+
NAME : ProcessPatternNode
|
898
|
+
DESCRIPTION : Determines if a pattern node satsifies the corresponding
|
899
|
+
slot value field(s) in an object. If it does,
|
900
|
+
ObjectPatternMatch() is recursively called to process
|
901
|
+
the child nodes of this node. In this mutual recursion
|
902
|
+
between ObjectPatternMatch() and ProcessPatternNode(),
|
903
|
+
the nodes of all applicable patterns are processed
|
904
|
+
to completion. ObjectPatternMatch() enters an object
|
905
|
+
into a pattern's aplha memory when the traversal reaches
|
906
|
+
a terminal class bitmap node.
|
907
|
+
INPUTS : 1) The offset of the slot index from the pattern index
|
908
|
+
2) The pattern node being examined
|
909
|
+
3) The end of the list of multifield markers for the pattern
|
910
|
+
RETURNS : Nothing useful
|
911
|
+
SIDE EFFECTS : The pattern tests are evaluated and the child nodes may
|
912
|
+
be processed (which may cause a whole series of Rete network
|
913
|
+
updates).
|
914
|
+
NOTES : Several globals are used to keep track of the current
|
915
|
+
slot being examined:
|
916
|
+
CurrentPatternMarks - the series of multifield markers
|
917
|
+
CurrentPatternObject - the object being pattern-matched
|
918
|
+
CurrentPatternObjectSlot - the current slot being examined
|
919
|
+
CurrentObjectSlotLength - the cardinality of the slot value
|
920
|
+
**********************************************************************************/
|
921
|
+
static void ProcessPatternNode(
|
922
|
+
Environment *theEnv,
|
923
|
+
size_t offset,
|
924
|
+
size_t multifieldsProcessed,
|
925
|
+
OBJECT_PATTERN_NODE *patternNode,
|
926
|
+
struct multifieldMarker *endMark)
|
927
|
+
{
|
928
|
+
unsigned short patternSlotField;
|
929
|
+
size_t objectSlotField;
|
930
|
+
size_t objectSlotLength;
|
931
|
+
size_t repeatCount;
|
932
|
+
InstanceSlot *objectSlot;
|
933
|
+
struct multifieldMarker *newMark;
|
934
|
+
UDFValue theResult;
|
935
|
+
OBJECT_PATTERN_NODE *tempPtr;
|
936
|
+
|
937
|
+
patternSlotField = patternNode->whichField;
|
938
|
+
|
939
|
+
objectSlotField = patternSlotField + offset - multifieldsProcessed;
|
940
|
+
|
941
|
+
/*============================================*/
|
942
|
+
/* If this is a test on the class or the name */
|
943
|
+
/* of the object, process it separately. */
|
944
|
+
/*============================================*/
|
945
|
+
|
946
|
+
if (ObjectReteData(theEnv)->CurrentPatternObjectSlot == NULL)
|
947
|
+
{
|
948
|
+
if (patternNode->selector) /* TBD Necessary? */
|
949
|
+
{
|
950
|
+
if (EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,patternNode->networkTest->nextArg,patternNode))
|
951
|
+
{
|
952
|
+
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
|
953
|
+
|
954
|
+
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
|
955
|
+
|
956
|
+
if (tempPtr != NULL)
|
957
|
+
{
|
958
|
+
if (tempPtr->alphaNode != NULL)
|
959
|
+
{ CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
|
960
|
+
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,tempPtr->nextLevel,endMark);
|
961
|
+
}
|
962
|
+
}
|
963
|
+
}
|
964
|
+
else if ((patternNode->networkTest == NULL) ? true :
|
965
|
+
(EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,
|
966
|
+
(Expression *) patternNode->networkTest,patternNode)))
|
967
|
+
{
|
968
|
+
if (patternNode->alphaNode != NULL)
|
969
|
+
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
|
970
|
+
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,patternNode->nextLevel,endMark);
|
971
|
+
}
|
972
|
+
return;
|
973
|
+
}
|
974
|
+
|
975
|
+
/*===================================*/
|
976
|
+
/* Check a single-field restriction. */
|
977
|
+
/*===================================*/
|
978
|
+
|
979
|
+
if (patternNode->multifieldNode == 0)
|
980
|
+
{
|
981
|
+
if (patternNode->selector)
|
982
|
+
{
|
983
|
+
if (EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,patternNode->networkTest->nextArg,patternNode))
|
984
|
+
{
|
985
|
+
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
|
986
|
+
|
987
|
+
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
|
988
|
+
|
989
|
+
if (tempPtr != NULL)
|
990
|
+
{
|
991
|
+
if (tempPtr->alphaNode != NULL)
|
992
|
+
{ CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
|
993
|
+
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,tempPtr->nextLevel,endMark);
|
994
|
+
}
|
995
|
+
}
|
996
|
+
}
|
997
|
+
else if ((patternNode->networkTest == NULL) ? true :
|
998
|
+
EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,
|
999
|
+
(Expression *) patternNode->networkTest,patternNode))
|
1000
|
+
{
|
1001
|
+
if (patternNode->alphaNode != NULL)
|
1002
|
+
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
|
1003
|
+
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,patternNode->nextLevel,endMark);
|
1004
|
+
}
|
1005
|
+
return;
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
/*==============================================================*/
|
1009
|
+
/* Check a multifield restriction. Add a marker for this field */
|
1010
|
+
/* which has indices indicating to which values in the object */
|
1011
|
+
/* slot the multifield pattern node is bound. */
|
1012
|
+
/*==============================================================*/
|
1013
|
+
|
1014
|
+
newMark = get_struct(theEnv,multifieldMarker);
|
1015
|
+
newMark->whichField = patternSlotField;
|
1016
|
+
newMark->where.whichSlot = (void *) ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->slotName->name;
|
1017
|
+
newMark->startPosition = objectSlotField;
|
1018
|
+
|
1019
|
+
newMark->next = NULL;
|
1020
|
+
if (ObjectReteData(theEnv)->CurrentPatternObjectMarks == NULL)
|
1021
|
+
ObjectReteData(theEnv)->CurrentPatternObjectMarks = newMark;
|
1022
|
+
else
|
1023
|
+
endMark->next = newMark;
|
1024
|
+
|
1025
|
+
/*============================================================*/
|
1026
|
+
/* If there are further pattern restrictions on this slot, */
|
1027
|
+
/* try pattern-matching for all possible bound values of the */
|
1028
|
+
/* multifield pattern node: from no values to all values from */
|
1029
|
+
/* the starting position of the multifield to the end of the */
|
1030
|
+
/* object slot. Otherwise, bind the multifield to all the */
|
1031
|
+
/* remaining fields in the slot value and continue with */
|
1032
|
+
/* pattern-matching. */
|
1033
|
+
/*============================================================*/
|
1034
|
+
|
1035
|
+
if (patternNode->endSlot == false)
|
1036
|
+
{
|
1037
|
+
objectSlotLength = ObjectReteData(theEnv)->CurrentObjectSlotLength;
|
1038
|
+
objectSlot = ObjectReteData(theEnv)->CurrentPatternObjectSlot;
|
1039
|
+
newMark->range = 0;
|
1040
|
+
|
1041
|
+
if ((objectSlotLength + 2) < (newMark->startPosition + patternNode->leaveFields))
|
1042
|
+
{ repeatCount = 0; }
|
1043
|
+
else
|
1044
|
+
{ repeatCount = objectSlotLength + 2 - newMark->startPosition - patternNode->leaveFields; }
|
1045
|
+
|
1046
|
+
while (repeatCount > 0)
|
1047
|
+
{
|
1048
|
+
if (patternNode->selector)
|
1049
|
+
{
|
1050
|
+
if (EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,patternNode->networkTest->nextArg,patternNode))
|
1051
|
+
{
|
1052
|
+
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
|
1053
|
+
|
1054
|
+
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
|
1055
|
+
|
1056
|
+
if (tempPtr != NULL)
|
1057
|
+
{
|
1058
|
+
if (tempPtr->alphaNode != NULL)
|
1059
|
+
{ CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
|
1060
|
+
ObjectPatternMatch(theEnv,offset + newMark->startPosition + newMark->range - objectSlotField,
|
1061
|
+
multifieldsProcessed+1,tempPtr->nextLevel,newMark);
|
1062
|
+
ObjectReteData(theEnv)->CurrentObjectSlotLength = objectSlotLength;
|
1063
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot = objectSlot;
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
}
|
1067
|
+
else if ((patternNode->networkTest == NULL) ? true :
|
1068
|
+
EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,
|
1069
|
+
(Expression *) patternNode->networkTest,patternNode))
|
1070
|
+
{
|
1071
|
+
if (patternNode->alphaNode != NULL)
|
1072
|
+
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
|
1073
|
+
ObjectPatternMatch(theEnv,offset + newMark->startPosition + newMark->range - objectSlotField,
|
1074
|
+
multifieldsProcessed+1,patternNode->nextLevel,newMark);
|
1075
|
+
ObjectReteData(theEnv)->CurrentObjectSlotLength = objectSlotLength;
|
1076
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot = objectSlot;
|
1077
|
+
}
|
1078
|
+
newMark->range++;
|
1079
|
+
repeatCount--;
|
1080
|
+
}
|
1081
|
+
}
|
1082
|
+
else
|
1083
|
+
{
|
1084
|
+
newMark->range = ObjectReteData(theEnv)->CurrentObjectSlotLength + 1 - newMark->startPosition - patternNode->leaveFields;
|
1085
|
+
if (patternNode->selector)
|
1086
|
+
{
|
1087
|
+
if (EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,patternNode->networkTest->nextArg,patternNode))
|
1088
|
+
{
|
1089
|
+
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
|
1090
|
+
|
1091
|
+
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
|
1092
|
+
|
1093
|
+
if (tempPtr != NULL)
|
1094
|
+
{
|
1095
|
+
if (tempPtr->alphaNode != NULL)
|
1096
|
+
CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode);
|
1097
|
+
ObjectPatternMatch(theEnv,0,0,tempPtr->nextLevel,newMark);
|
1098
|
+
}
|
1099
|
+
}
|
1100
|
+
}
|
1101
|
+
else if ((patternNode->networkTest == NULL) ? true :
|
1102
|
+
EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,
|
1103
|
+
(Expression *) patternNode->networkTest,patternNode))
|
1104
|
+
{
|
1105
|
+
if (patternNode->alphaNode != NULL)
|
1106
|
+
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
|
1107
|
+
ObjectPatternMatch(theEnv,0,0,patternNode->nextLevel,newMark);
|
1108
|
+
}
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
/*=========================================*/
|
1112
|
+
/* Delete the temporary multifield marker. */
|
1113
|
+
/*=========================================*/
|
1114
|
+
|
1115
|
+
if (ObjectReteData(theEnv)->CurrentPatternObjectMarks == newMark)
|
1116
|
+
ObjectReteData(theEnv)->CurrentPatternObjectMarks = NULL;
|
1117
|
+
else
|
1118
|
+
endMark->next = NULL;
|
1119
|
+
rtn_struct(theEnv,multifieldMarker,newMark);
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
/***************************************************
|
1123
|
+
NAME : CreateObjectAlphaMatch
|
1124
|
+
DESCRIPTION : Places an instance in the alpha
|
1125
|
+
memory of a pattern and drives the
|
1126
|
+
partial match through the join
|
1127
|
+
network
|
1128
|
+
INPUTS : The alpha memory node
|
1129
|
+
RETURNS : Nothing useful
|
1130
|
+
SIDE EFFECTS : Join network updated
|
1131
|
+
NOTES : None
|
1132
|
+
***************************************************/
|
1133
|
+
static void CreateObjectAlphaMatch(
|
1134
|
+
Environment *theEnv,
|
1135
|
+
OBJECT_ALPHA_NODE *alphaPtr)
|
1136
|
+
{
|
1137
|
+
struct joinNode *listOfJoins;
|
1138
|
+
struct partialMatch *theMatch;
|
1139
|
+
struct patternMatch *newMatch;
|
1140
|
+
unsigned long hashValue;
|
1141
|
+
|
1142
|
+
while (alphaPtr != NULL)
|
1143
|
+
{
|
1144
|
+
if (alphaPtr->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
|
1145
|
+
{
|
1146
|
+
hashValue = ComputeRightHashValue(theEnv,&alphaPtr->header);
|
1147
|
+
|
1148
|
+
/* ===================================================
|
1149
|
+
If we have reached the class bitmap of the pattern,
|
1150
|
+
place the object in the alpha memory of each of
|
1151
|
+
the terminal nodes underneath and drive
|
1152
|
+
the partial matches through the join network.
|
1153
|
+
|
1154
|
+
Insert the instance into the alpha memory
|
1155
|
+
of this pattern and mark it as busy
|
1156
|
+
=================================================== */
|
1157
|
+
ObjectReteData(theEnv)->CurrentPatternObject->busy++;
|
1158
|
+
theMatch = CreateAlphaMatch(theEnv,ObjectReteData(theEnv)->CurrentPatternObject,
|
1159
|
+
ObjectReteData(theEnv)->CurrentPatternObjectMarks,
|
1160
|
+
(struct patternNodeHeader *) alphaPtr,hashValue);
|
1161
|
+
theMatch->owner = alphaPtr;
|
1162
|
+
|
1163
|
+
/* ======================================
|
1164
|
+
Attach the partial match to the object
|
1165
|
+
to ease later retraction
|
1166
|
+
====================================== */
|
1167
|
+
newMatch = get_struct(theEnv,patternMatch);
|
1168
|
+
newMatch->next = (struct patternMatch *) ObjectReteData(theEnv)->CurrentPatternObject->partialMatchList;
|
1169
|
+
newMatch->matchingPattern = (struct patternNodeHeader *) alphaPtr;
|
1170
|
+
newMatch->theMatch = theMatch;
|
1171
|
+
ObjectReteData(theEnv)->CurrentPatternObject->partialMatchList = (void *) newMatch;
|
1172
|
+
|
1173
|
+
/* ================================================
|
1174
|
+
Drive the partial match through the join network
|
1175
|
+
================================================ */
|
1176
|
+
listOfJoins = alphaPtr->header.entryJoin;
|
1177
|
+
while (listOfJoins != NULL)
|
1178
|
+
{
|
1179
|
+
NetworkAssert(theEnv,theMatch,listOfJoins);
|
1180
|
+
listOfJoins = listOfJoins->rightMatchNode;
|
1181
|
+
}
|
1182
|
+
}
|
1183
|
+
alphaPtr = alphaPtr->nxtInGroup;
|
1184
|
+
}
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
/******************************************************
|
1188
|
+
NAME : EvaluateObjectPatternTest
|
1189
|
+
DESCRIPTION : Evaluates the pattern network test
|
1190
|
+
expression for a node
|
1191
|
+
INPUTS : 1) The actual index of the slot value
|
1192
|
+
field currently being examined
|
1193
|
+
2) The multifield marker (if any)
|
1194
|
+
for the pattern node being exmained
|
1195
|
+
3) The pattern network test expression
|
1196
|
+
4) The pattern node being examined
|
1197
|
+
RETURNS : True if the node passes the
|
1198
|
+
test, false otherwise
|
1199
|
+
SIDE EFFECTS : Evaluation of the test
|
1200
|
+
EvaluationError and HaltExecution
|
1201
|
+
are always set to false
|
1202
|
+
NOTES : Assumes networkTest != NULL
|
1203
|
+
******************************************************/
|
1204
|
+
static bool EvaluateObjectPatternTest(
|
1205
|
+
Environment *theEnv,
|
1206
|
+
size_t objectSlotField,
|
1207
|
+
struct multifieldMarker *selfSlotMarker,
|
1208
|
+
Expression *networkTest,
|
1209
|
+
OBJECT_PATTERN_NODE *patternNode)
|
1210
|
+
{
|
1211
|
+
UDFValue vresult;
|
1212
|
+
int rv;
|
1213
|
+
|
1214
|
+
if (networkTest == NULL) return true;
|
1215
|
+
|
1216
|
+
if (networkTest->type == OBJ_PN_CONSTANT)
|
1217
|
+
{
|
1218
|
+
struct expr *oldArgument;
|
1219
|
+
|
1220
|
+
oldArgument = EvaluationData(theEnv)->CurrentExpression;
|
1221
|
+
EvaluationData(theEnv)->CurrentExpression = networkTest;
|
1222
|
+
rv = ObjectCmpConstantFunction(theEnv,networkTest->value,&vresult);
|
1223
|
+
EvaluationData(theEnv)->CurrentExpression = oldArgument;
|
1224
|
+
if (rv)
|
1225
|
+
{
|
1226
|
+
if (((const struct ObjectCmpPNConstant *)
|
1227
|
+
networkTest->bitMapValue->contents)->pass)
|
1228
|
+
patternNode->blocked = true;
|
1229
|
+
return true;
|
1230
|
+
}
|
1231
|
+
return false;
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
/* =========================================================
|
1235
|
+
Evaluate or expressions expressed in the format:
|
1236
|
+
(or <expression 1> <expression 2> ... <expression n>)
|
1237
|
+
Returns true (1.0) if any of the expression are true,
|
1238
|
+
otherwise returns false (0.0).
|
1239
|
+
========================================================= */
|
1240
|
+
if (networkTest->value == ExpressionData(theEnv)->PTR_OR)
|
1241
|
+
{
|
1242
|
+
networkTest = networkTest->argList;
|
1243
|
+
while (networkTest != NULL)
|
1244
|
+
{
|
1245
|
+
if (EvaluateObjectPatternTest(theEnv,objectSlotField,selfSlotMarker,networkTest,patternNode))
|
1246
|
+
{
|
1247
|
+
/* ============================================
|
1248
|
+
A node can be blocked ONLY if there were one
|
1249
|
+
positive constant test on that node
|
1250
|
+
============================================ */
|
1251
|
+
patternNode->blocked = false;
|
1252
|
+
return true;
|
1253
|
+
}
|
1254
|
+
patternNode->blocked = false;
|
1255
|
+
networkTest = networkTest->nextArg;
|
1256
|
+
}
|
1257
|
+
return false;
|
1258
|
+
}
|
1259
|
+
|
1260
|
+
/* ==========================================================
|
1261
|
+
Evaluate and expressions expressed in the format:
|
1262
|
+
(and <expression 1> <expression 2> ... <expression n>)
|
1263
|
+
Returns false if any of the expression are false,
|
1264
|
+
otherwise returns true.
|
1265
|
+
========================================================== */
|
1266
|
+
else if (networkTest->value == ExpressionData(theEnv)->PTR_AND)
|
1267
|
+
{
|
1268
|
+
networkTest = networkTest->argList;
|
1269
|
+
while (networkTest != NULL)
|
1270
|
+
{
|
1271
|
+
if (EvaluateObjectPatternTest(theEnv,objectSlotField,selfSlotMarker,networkTest,patternNode)
|
1272
|
+
== false)
|
1273
|
+
{
|
1274
|
+
patternNode->blocked = false;
|
1275
|
+
return false;
|
1276
|
+
}
|
1277
|
+
patternNode->blocked = false;
|
1278
|
+
networkTest = networkTest->nextArg;
|
1279
|
+
}
|
1280
|
+
return true;
|
1281
|
+
}
|
1282
|
+
|
1283
|
+
/* =======================================================
|
1284
|
+
Evaluate all other expressions using EvaluateExpression
|
1285
|
+
======================================================= */
|
1286
|
+
else
|
1287
|
+
{
|
1288
|
+
EvaluationData(theEnv)->HaltExecution = false;
|
1289
|
+
if (EvaluateExpression(theEnv,networkTest,&vresult))
|
1290
|
+
{
|
1291
|
+
ObjectPatternNetErrorMessage(theEnv,patternNode);
|
1292
|
+
EvaluationData(theEnv)->EvaluationError = false;
|
1293
|
+
EvaluationData(theEnv)->HaltExecution = false;
|
1294
|
+
return false;
|
1295
|
+
}
|
1296
|
+
if (vresult.value != FalseSymbol(theEnv))
|
1297
|
+
return true;
|
1298
|
+
}
|
1299
|
+
return false;
|
1300
|
+
}
|
1301
|
+
|
1302
|
+
/***************************************************
|
1303
|
+
NAME : ObjectAssertAction
|
1304
|
+
DESCRIPTION : Filters an instance through the
|
1305
|
+
object pattern network
|
1306
|
+
INPUTS : The instance
|
1307
|
+
RETURNS : Nothing useful
|
1308
|
+
SIDE EFFECTS : Instance matched
|
1309
|
+
NOTES : None
|
1310
|
+
***************************************************/
|
1311
|
+
static void ObjectAssertAction(
|
1312
|
+
Environment *theEnv,
|
1313
|
+
Instance *ins)
|
1314
|
+
{
|
1315
|
+
ins->patternHeader.timeTag = ObjectReteData(theEnv)->UseEntityTimeTag;
|
1316
|
+
ObjectReteData(theEnv)->CurrentPatternObject = ins;
|
1317
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
|
1318
|
+
MarkObjectPatternNetwork(theEnv,NULL);
|
1319
|
+
ObjectPatternMatch(theEnv,0,0,ObjectNetworkPointer(theEnv),NULL);
|
1320
|
+
ins->reteSynchronized = true;
|
1321
|
+
}
|
1322
|
+
|
1323
|
+
/**********************************************************************
|
1324
|
+
NAME : ObjectModifyAction
|
1325
|
+
DESCRIPTION : Removes an instance from patterns (and attached joins)
|
1326
|
+
applicable to specified slot(s), and then filters
|
1327
|
+
same instance through object pattern network
|
1328
|
+
(only against patterns which explicitly match on
|
1329
|
+
named slot(s))
|
1330
|
+
INPUTS : 1) The instance
|
1331
|
+
2) The bitmap of slot ids
|
1332
|
+
RETURNS : Nothing useful
|
1333
|
+
SIDE EFFECTS : Instance retracted/asserted
|
1334
|
+
NOTES : None
|
1335
|
+
**********************************************************************/
|
1336
|
+
static void ObjectModifyAction(
|
1337
|
+
Environment *theEnv,
|
1338
|
+
Instance *ins,
|
1339
|
+
SLOT_BITMAP *slotNameIDs)
|
1340
|
+
{
|
1341
|
+
ins->patternHeader.timeTag = ObjectReteData(theEnv)->UseEntityTimeTag;
|
1342
|
+
ObjectRetractAction(theEnv,ins,slotNameIDs);
|
1343
|
+
ObjectReteData(theEnv)->CurrentPatternObject = ins;
|
1344
|
+
ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
|
1345
|
+
MarkObjectPatternNetwork(theEnv,slotNameIDs);
|
1346
|
+
ObjectPatternMatch(theEnv,0,0,ObjectNetworkPointer(theEnv),NULL);
|
1347
|
+
ins->reteSynchronized = true;
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
/****************************************************
|
1351
|
+
NAME : ObjectRetractAction
|
1352
|
+
DESCRIPTION : Retracts the instance from the
|
1353
|
+
applicable patterns for the object
|
1354
|
+
(if the slotNameID != -1, then the
|
1355
|
+
instance is only retracted from
|
1356
|
+
the alpha memories of the patterns
|
1357
|
+
which actually match on that slot)
|
1358
|
+
INPUTS : 1) The instance
|
1359
|
+
2) The slot bitmap for a modify
|
1360
|
+
(NULL if the instance is actually
|
1361
|
+
being removed)
|
1362
|
+
RETURNS : Nothing useful
|
1363
|
+
SIDE EFFECTS : Retractions performed
|
1364
|
+
NOTES : None
|
1365
|
+
****************************************************/
|
1366
|
+
static void ObjectRetractAction(
|
1367
|
+
Environment *theEnv,
|
1368
|
+
Instance *ins,
|
1369
|
+
SLOT_BITMAP *slotNameIDs)
|
1370
|
+
{
|
1371
|
+
struct patternMatch *prvMatch,*tmpMatch,
|
1372
|
+
*deleteMatch,*lastDeleteMatch;
|
1373
|
+
OBJECT_ALPHA_NODE *alphaPtr;
|
1374
|
+
void *saveDependents;
|
1375
|
+
|
1376
|
+
if (slotNameIDs == NULL)
|
1377
|
+
{
|
1378
|
+
if (ins->partialMatchList != NULL)
|
1379
|
+
{
|
1380
|
+
tmpMatch = (struct patternMatch *) ins->partialMatchList;
|
1381
|
+
while (tmpMatch != NULL)
|
1382
|
+
{
|
1383
|
+
ins->busy--;
|
1384
|
+
tmpMatch = tmpMatch->next;
|
1385
|
+
}
|
1386
|
+
NetworkRetract(theEnv,(struct patternMatch *) ins->partialMatchList);
|
1387
|
+
ins->partialMatchList = NULL;
|
1388
|
+
}
|
1389
|
+
}
|
1390
|
+
else
|
1391
|
+
{
|
1392
|
+
deleteMatch = NULL;
|
1393
|
+
lastDeleteMatch = NULL;
|
1394
|
+
prvMatch = NULL;
|
1395
|
+
tmpMatch = (struct patternMatch *) ins->partialMatchList;
|
1396
|
+
while (tmpMatch != NULL)
|
1397
|
+
{
|
1398
|
+
alphaPtr = (OBJECT_ALPHA_NODE *) tmpMatch->matchingPattern;
|
1399
|
+
if (alphaPtr->slotbmp != NULL)
|
1400
|
+
{
|
1401
|
+
if (CompareSlotBitMaps(slotNameIDs,
|
1402
|
+
(const SLOT_BITMAP *) alphaPtr->slotbmp->contents))
|
1403
|
+
{
|
1404
|
+
ins->busy--;
|
1405
|
+
if (prvMatch == NULL)
|
1406
|
+
ins->partialMatchList = (void *) tmpMatch->next;
|
1407
|
+
else
|
1408
|
+
prvMatch->next = tmpMatch->next;
|
1409
|
+
if (!deleteMatch)
|
1410
|
+
deleteMatch = tmpMatch;
|
1411
|
+
else
|
1412
|
+
lastDeleteMatch->next = tmpMatch;
|
1413
|
+
lastDeleteMatch = tmpMatch;
|
1414
|
+
tmpMatch = tmpMatch->next;
|
1415
|
+
lastDeleteMatch->next = NULL;
|
1416
|
+
}
|
1417
|
+
else
|
1418
|
+
{
|
1419
|
+
prvMatch = tmpMatch;
|
1420
|
+
tmpMatch = tmpMatch->next;
|
1421
|
+
}
|
1422
|
+
}
|
1423
|
+
else
|
1424
|
+
{
|
1425
|
+
prvMatch = tmpMatch;
|
1426
|
+
tmpMatch = tmpMatch->next;
|
1427
|
+
}
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
/* =============================================
|
1431
|
+
We need to preserve any logical dependencies
|
1432
|
+
of this object and reattach them after doing
|
1433
|
+
the retract. Otherwise, the Rete network
|
1434
|
+
will believe the object is gone and remove
|
1435
|
+
the links from the partial matches upon which
|
1436
|
+
this object is logically dependent.
|
1437
|
+
============================================= */
|
1438
|
+
if (deleteMatch != NULL)
|
1439
|
+
{
|
1440
|
+
saveDependents = ins->patternHeader.dependents;
|
1441
|
+
ins->patternHeader.dependents = NULL;
|
1442
|
+
NetworkRetract(theEnv,deleteMatch);
|
1443
|
+
ins->patternHeader.dependents = saveDependents;
|
1444
|
+
}
|
1445
|
+
}
|
1446
|
+
|
1447
|
+
if (ins->dataRemovalDeferred)
|
1448
|
+
{
|
1449
|
+
ins->dataRemovalDeferred = false;
|
1450
|
+
RemoveInstanceData(theEnv,ins);
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
ins->reteSynchronized = true;
|
1454
|
+
}
|
1455
|
+
|
1456
|
+
/*****************************************************
|
1457
|
+
NAME : ObjectPatternNetErrorMessage
|
1458
|
+
DESCRIPTION : Prints out a locational error message
|
1459
|
+
when an evaluation error occurs
|
1460
|
+
during object pattern-matching
|
1461
|
+
INPUTS : The pattern node
|
1462
|
+
RETURNS : Nothing useful
|
1463
|
+
SIDE EFFECTS : Error message displayed
|
1464
|
+
NOTES : None
|
1465
|
+
*****************************************************/
|
1466
|
+
static void ObjectPatternNetErrorMessage(
|
1467
|
+
Environment *theEnv,
|
1468
|
+
OBJECT_PATTERN_NODE *patternPtr)
|
1469
|
+
{
|
1470
|
+
PrintErrorID(theEnv,"OBJRTMCH",1,true);
|
1471
|
+
WriteString(theEnv,STDERR,"This error occurred in the object pattern network\n");
|
1472
|
+
WriteString(theEnv,STDERR," Currently active instance: [");
|
1473
|
+
WriteString(theEnv,STDERR,ObjectReteData(theEnv)->CurrentPatternObject->name->contents);
|
1474
|
+
WriteString(theEnv,STDERR,"]\n");
|
1475
|
+
WriteString(theEnv,STDERR," Problem resides in slot '");
|
1476
|
+
WriteString(theEnv,STDERR,FindIDSlotName(theEnv,patternPtr->slotNameID)->contents);
|
1477
|
+
WriteString(theEnv,STDERR,"' field #");
|
1478
|
+
PrintUnsignedInteger(theEnv,STDERR,patternPtr->whichField);
|
1479
|
+
WriteString(theEnv,STDERR,"\n");
|
1480
|
+
TraceErrorToObjectPattern(theEnv,true,patternPtr);
|
1481
|
+
WriteString(theEnv,STDERR,"\n");
|
1482
|
+
}
|
1483
|
+
|
1484
|
+
/*********************************************************
|
1485
|
+
NAME : TraceErrorToObjectPattern
|
1486
|
+
DESCRIPTION : Used by ObjectPatternNetErrorMessage() to
|
1487
|
+
print the rule(s) which contain an object
|
1488
|
+
pattern.
|
1489
|
+
INPUTS : 1) A flag indicating if this is the
|
1490
|
+
node in which the error actually
|
1491
|
+
occurred or not
|
1492
|
+
2) The pattern node
|
1493
|
+
RETURNS : Nothing useful
|
1494
|
+
SIDE EFFECTS : Error message displayed
|
1495
|
+
NOTES : None
|
1496
|
+
*********************************************************/
|
1497
|
+
static void TraceErrorToObjectPattern(
|
1498
|
+
Environment *theEnv,
|
1499
|
+
bool errorNode,
|
1500
|
+
OBJECT_PATTERN_NODE *patternPtr)
|
1501
|
+
{
|
1502
|
+
struct joinNode *joinPtr;
|
1503
|
+
|
1504
|
+
while (patternPtr != NULL)
|
1505
|
+
{
|
1506
|
+
if (patternPtr->alphaNode != NULL)
|
1507
|
+
{
|
1508
|
+
joinPtr = patternPtr->alphaNode->header.entryJoin;
|
1509
|
+
while (joinPtr != NULL)
|
1510
|
+
{
|
1511
|
+
TraceErrorToRule(theEnv,joinPtr," ");
|
1512
|
+
joinPtr = joinPtr->rightMatchNode;
|
1513
|
+
}
|
1514
|
+
}
|
1515
|
+
TraceErrorToObjectPattern(theEnv,false,patternPtr->nextLevel);
|
1516
|
+
if (errorNode)
|
1517
|
+
break;
|
1518
|
+
patternPtr = patternPtr->rightNode;
|
1519
|
+
}
|
1520
|
+
|
1521
|
+
}
|
1522
|
+
|
1523
|
+
#endif
|
1524
|
+
|