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,2393 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.40 02/03/21 */
|
5
|
+
/* */
|
6
|
+
/* OBJECT PATTERN MATCHER MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: RETE Network Parsing Interface for Objects */
|
11
|
+
/* */
|
12
|
+
/* Principal Programmer(s): */
|
13
|
+
/* Brian L. Dantes */
|
14
|
+
/* */
|
15
|
+
/* Contributing Programmer(s): */
|
16
|
+
/* */
|
17
|
+
/* Revision History: */
|
18
|
+
/* */
|
19
|
+
/* 6.24: Removed INCREMENTAL_RESET compilation flag. */
|
20
|
+
/* */
|
21
|
+
/* Converted INSTANCE_PATTERN_MATCHING to */
|
22
|
+
/* DEFRULE_CONSTRUCT. */
|
23
|
+
/* */
|
24
|
+
/* Renamed BOOLEAN macro type to intBool. */
|
25
|
+
/* */
|
26
|
+
/* 6.30: Changed integer type/precision. */
|
27
|
+
/* */
|
28
|
+
/* Removed conditional code for unsupported */
|
29
|
+
/* compilers/operating systems (IBM_MCW, */
|
30
|
+
/* MAC_MCW, and IBM_TBC). */
|
31
|
+
/* */
|
32
|
+
/* Support for long long integers. */
|
33
|
+
/* */
|
34
|
+
/* Added support for hashed comparisons to */
|
35
|
+
/* constants. */
|
36
|
+
/* */
|
37
|
+
/* Added support for hashed alpha memories. */
|
38
|
+
/* */
|
39
|
+
/* Added const qualifiers to remove C++ */
|
40
|
+
/* deprecation warnings. */
|
41
|
+
/* */
|
42
|
+
/* 6.31: Added class name to OBJRTBLD5 error message. */
|
43
|
+
/* */
|
44
|
+
/* Optimization for marking relevant alpha nodes */
|
45
|
+
/* in the object pattern network. */
|
46
|
+
/* */
|
47
|
+
/* 6.40: Pragma once and other inclusion changes. */
|
48
|
+
/* */
|
49
|
+
/* Added support for booleans with <stdbool.h>. */
|
50
|
+
/* */
|
51
|
+
/* Removed use of void pointers for specific */
|
52
|
+
/* data structures. */
|
53
|
+
/* */
|
54
|
+
/* Static constraint checking is always enabled. */
|
55
|
+
/* */
|
56
|
+
/* UDF redesign. */
|
57
|
+
/* */
|
58
|
+
/* Removed initial-object support. */
|
59
|
+
/* */
|
60
|
+
/*************************************************************/
|
61
|
+
/* =========================================
|
62
|
+
*****************************************
|
63
|
+
EXTERNAL DEFINITIONS
|
64
|
+
=========================================
|
65
|
+
***************************************** */
|
66
|
+
#include "setup.h"
|
67
|
+
|
68
|
+
#if DEFRULE_CONSTRUCT && OBJECT_SYSTEM
|
69
|
+
|
70
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
71
|
+
|
72
|
+
#include <string.h>
|
73
|
+
#include <stdlib.h>
|
74
|
+
|
75
|
+
#include "classcom.h"
|
76
|
+
#include "classfun.h"
|
77
|
+
#include "cstrnutl.h"
|
78
|
+
#include "constrnt.h"
|
79
|
+
#include "cstrnchk.h"
|
80
|
+
#include "cstrnops.h"
|
81
|
+
#include "drive.h"
|
82
|
+
#include "envrnmnt.h"
|
83
|
+
#include "inscom.h"
|
84
|
+
#include "insfun.h"
|
85
|
+
#include "insmngr.h"
|
86
|
+
#include "memalloc.h"
|
87
|
+
#include "network.h"
|
88
|
+
#include "object.h"
|
89
|
+
#include "pattern.h"
|
90
|
+
#include "prntutil.h"
|
91
|
+
#include "reteutil.h"
|
92
|
+
#include "ruledef.h"
|
93
|
+
#include "rulepsr.h"
|
94
|
+
#include "scanner.h"
|
95
|
+
#include "symbol.h"
|
96
|
+
#include "utility.h"
|
97
|
+
|
98
|
+
#endif
|
99
|
+
|
100
|
+
#include "constrct.h"
|
101
|
+
#include "exprnpsr.h"
|
102
|
+
#include "objrtmch.h"
|
103
|
+
#include "objrtgen.h"
|
104
|
+
#include "objrtfnx.h"
|
105
|
+
#include "pprint.h"
|
106
|
+
#include "reorder.h"
|
107
|
+
#include "router.h"
|
108
|
+
|
109
|
+
#if BLOAD_AND_BSAVE || BLOAD || BLOAD_ONLY
|
110
|
+
#include "objrtbin.h"
|
111
|
+
#endif
|
112
|
+
|
113
|
+
#if CONSTRUCT_COMPILER && (! RUN_TIME)
|
114
|
+
#include "objrtcmp.h"
|
115
|
+
#endif
|
116
|
+
|
117
|
+
#include "objrtbld.h"
|
118
|
+
|
119
|
+
#if ! DEFINSTANCES_CONSTRUCT
|
120
|
+
#include "classfun.h"
|
121
|
+
#include "classcom.h"
|
122
|
+
#include "extnfunc.h"
|
123
|
+
#endif
|
124
|
+
|
125
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
126
|
+
|
127
|
+
/* =========================================
|
128
|
+
*****************************************
|
129
|
+
CONSTANTS
|
130
|
+
=========================================
|
131
|
+
***************************************** */
|
132
|
+
#define OBJECT_PATTERN_INDICATOR "object"
|
133
|
+
|
134
|
+
/* =========================================
|
135
|
+
*****************************************
|
136
|
+
INTERNALLY VISIBLE FUNCTION HEADERS
|
137
|
+
=========================================
|
138
|
+
***************************************** */
|
139
|
+
|
140
|
+
static bool PatternParserFind(CLIPSLexeme *);
|
141
|
+
static struct lhsParseNode *ObjectLHSParse(Environment *,const char *,struct token *);
|
142
|
+
static bool ReorderAndAnalyzeObjectPattern(Environment *,struct lhsParseNode *);
|
143
|
+
static struct patternNodeHeader
|
144
|
+
*PlaceObjectPattern(Environment *,struct lhsParseNode *);
|
145
|
+
static OBJECT_PATTERN_NODE *FindObjectPatternNode(OBJECT_PATTERN_NODE *,struct lhsParseNode *,
|
146
|
+
OBJECT_PATTERN_NODE **,bool,bool);
|
147
|
+
static OBJECT_PATTERN_NODE *CreateNewObjectPatternNode(Environment *,struct lhsParseNode *,OBJECT_PATTERN_NODE *,
|
148
|
+
OBJECT_PATTERN_NODE *,bool,bool);
|
149
|
+
static void DetachObjectPattern(Environment *,struct patternNodeHeader *);
|
150
|
+
static void ClearObjectPatternMatches(Environment *,OBJECT_ALPHA_NODE *);
|
151
|
+
static void RemoveObjectPartialMatches(Environment *,Instance *,struct patternNodeHeader *);
|
152
|
+
static bool CheckDuplicateSlots(Environment *,struct lhsParseNode *,CLIPSLexeme *);
|
153
|
+
static struct lhsParseNode *ParseClassRestriction(Environment *,const char *,struct token *);
|
154
|
+
static struct lhsParseNode *ParseNameRestriction(Environment *,const char *,struct token *);
|
155
|
+
static struct lhsParseNode *ParseSlotRestriction(Environment *,const char *,struct token *,CONSTRAINT_RECORD *,bool);
|
156
|
+
static CLASS_BITMAP *NewClassBitMap(Environment *,unsigned short,bool);
|
157
|
+
static void InitializeClassBitMap(Environment *,CLASS_BITMAP *,bool);
|
158
|
+
static void DeleteIntermediateClassBitMap(Environment *,const CLASS_BITMAP *);
|
159
|
+
static void *CopyClassBitMap(Environment *,void *);
|
160
|
+
static void DeleteClassBitMap(Environment *,void *);
|
161
|
+
static void MarkBitMapClassesBusy(Environment *,CLIPSBitMap *,int);
|
162
|
+
static bool EmptyClassBitMap(CLASS_BITMAP *);
|
163
|
+
static bool IdenticalClassBitMap(const CLASS_BITMAP *,const CLASS_BITMAP *);
|
164
|
+
static bool ProcessClassRestriction(Environment *,CLASS_BITMAP *,struct lhsParseNode **,bool);
|
165
|
+
static CONSTRAINT_RECORD *ProcessSlotRestriction(Environment *,CLASS_BITMAP *,CLIPSLexeme *,bool *);
|
166
|
+
static void IntersectClassBitMaps(CLASS_BITMAP *,CLASS_BITMAP *);
|
167
|
+
static void UnionClassBitMaps(CLASS_BITMAP *,CLASS_BITMAP *);
|
168
|
+
static CLASS_BITMAP *PackClassBitMap(Environment *,CLASS_BITMAP *);
|
169
|
+
static struct lhsParseNode *FilterObjectPattern(Environment *,struct patternParser *,
|
170
|
+
struct lhsParseNode *,struct lhsParseNode **,
|
171
|
+
struct lhsParseNode **,struct lhsParseNode **);
|
172
|
+
static CLIPSBitMap *FormSlotBitMap(Environment *,struct lhsParseNode *);
|
173
|
+
static struct lhsParseNode *RemoveSlotExistenceTests(Environment *,struct lhsParseNode *,CLIPSBitMap **);
|
174
|
+
static void MarkObjectPtnIncrementalReset(Environment *,struct patternNodeHeader *,bool);
|
175
|
+
static void ObjectIncrementalReset(Environment *);
|
176
|
+
|
177
|
+
#endif
|
178
|
+
|
179
|
+
static Expression *ObjectMatchDelayParse(Environment *,Expression *,const char *);
|
180
|
+
|
181
|
+
/* =========================================
|
182
|
+
*****************************************
|
183
|
+
EXTERNALLY VISIBLE FUNCTIONS
|
184
|
+
=========================================
|
185
|
+
***************************************** */
|
186
|
+
|
187
|
+
/********************************************************
|
188
|
+
NAME : SetupObjectPatternStuff
|
189
|
+
DESCRIPTION : Installs the parsers and other items
|
190
|
+
necessary for recognizing and processing
|
191
|
+
object patterns in defrules
|
192
|
+
INPUTS : None
|
193
|
+
RETURNS : Nothing useful
|
194
|
+
SIDE EFFECTS : Rete network interfaces for objects
|
195
|
+
initialized
|
196
|
+
NOTES : None
|
197
|
+
********************************************************/
|
198
|
+
void SetupObjectPatternStuff(
|
199
|
+
Environment *theEnv)
|
200
|
+
{
|
201
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
202
|
+
struct patternParser *newPtr;
|
203
|
+
|
204
|
+
if (ReservedPatternSymbol(theEnv,"object",NULL) == true)
|
205
|
+
{
|
206
|
+
SystemError(theEnv,"OBJRTBLD",1);
|
207
|
+
ExitRouter(theEnv,EXIT_FAILURE);
|
208
|
+
}
|
209
|
+
AddReservedPatternSymbol(theEnv,"object",NULL);
|
210
|
+
|
211
|
+
/* ===========================================================================
|
212
|
+
The object pattern parser needs to have a higher priority than deftemplates
|
213
|
+
or regular facts so that the "object" keyword is always recognized first
|
214
|
+
=========================================================================== */
|
215
|
+
|
216
|
+
newPtr = get_struct(theEnv,patternParser);
|
217
|
+
|
218
|
+
newPtr->name = "objects";
|
219
|
+
newPtr->priority = 20;
|
220
|
+
newPtr->entityType = &InstanceData(theEnv)->InstanceInfo;
|
221
|
+
|
222
|
+
newPtr->recognizeFunction = PatternParserFind;
|
223
|
+
newPtr->parseFunction = ObjectLHSParse;
|
224
|
+
newPtr->postAnalysisFunction = ReorderAndAnalyzeObjectPattern;
|
225
|
+
newPtr->addPatternFunction = PlaceObjectPattern;
|
226
|
+
newPtr->removePatternFunction = DetachObjectPattern;
|
227
|
+
newPtr->genJNConstantFunction = NULL;
|
228
|
+
newPtr->replaceGetJNValueFunction = ReplaceGetJNObjectValue;
|
229
|
+
newPtr->genGetJNValueFunction = GenGetJNObjectValue;
|
230
|
+
newPtr->genCompareJNValuesFunction = ObjectJNVariableComparison;
|
231
|
+
newPtr->genPNConstantFunction = GenObjectPNConstantCompare;
|
232
|
+
newPtr->replaceGetPNValueFunction = ReplaceGetPNObjectValue;
|
233
|
+
newPtr->genGetPNValueFunction = GenGetPNObjectValue;
|
234
|
+
newPtr->genComparePNValuesFunction = ObjectPNVariableComparison;
|
235
|
+
newPtr->returnUserDataFunction = DeleteClassBitMap;
|
236
|
+
newPtr->copyUserDataFunction = CopyClassBitMap;
|
237
|
+
|
238
|
+
newPtr->markIRPatternFunction = MarkObjectPtnIncrementalReset;
|
239
|
+
newPtr->incrementalResetFunction = ObjectIncrementalReset;
|
240
|
+
|
241
|
+
#if CONSTRUCT_COMPILER && (! RUN_TIME)
|
242
|
+
newPtr->codeReferenceFunction = ObjectPatternNodeReference;
|
243
|
+
#else
|
244
|
+
newPtr->codeReferenceFunction = NULL;
|
245
|
+
#endif
|
246
|
+
|
247
|
+
AddPatternParser(theEnv,newPtr);
|
248
|
+
|
249
|
+
#endif
|
250
|
+
|
251
|
+
#if (! RUN_TIME)
|
252
|
+
AddUDF(theEnv,"object-pattern-match-delay","*",0,UNBOUNDED,NULL,ObjectMatchDelay,"ObjectMatchDelay",NULL);
|
253
|
+
FuncSeqOvlFlags(theEnv,"object-pattern-match-delay",false,false);
|
254
|
+
#endif
|
255
|
+
|
256
|
+
AddFunctionParser(theEnv,"object-pattern-match-delay",ObjectMatchDelayParse);
|
257
|
+
|
258
|
+
InstallObjectPrimitives(theEnv);
|
259
|
+
|
260
|
+
#if CONSTRUCT_COMPILER && (! RUN_TIME)
|
261
|
+
ObjectPatternsCompilerSetup(theEnv);
|
262
|
+
#endif
|
263
|
+
|
264
|
+
#if BLOAD_AND_BSAVE || BLOAD || BLOAD_ONLY
|
265
|
+
SetupObjectPatternsBload(theEnv);
|
266
|
+
#endif
|
267
|
+
}
|
268
|
+
|
269
|
+
/* =========================================
|
270
|
+
*****************************************
|
271
|
+
INTERNALLY VISIBLE FUNCTIONS
|
272
|
+
=========================================
|
273
|
+
***************************************** */
|
274
|
+
|
275
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
276
|
+
|
277
|
+
/*****************************************************
|
278
|
+
NAME : PatternParserFind
|
279
|
+
DESCRIPTION : Determines if a pattern CE is an
|
280
|
+
object pattern (i.e. the first field
|
281
|
+
is the constant symbol "object")
|
282
|
+
INPUTS : 1) The type of the first field
|
283
|
+
2) The value of the first field
|
284
|
+
RETURNS : True if it is an object pattern,
|
285
|
+
false otherwise
|
286
|
+
SIDE EFFECTS : None
|
287
|
+
NOTES : Used by AddPatternParser()
|
288
|
+
*****************************************************/
|
289
|
+
static bool PatternParserFind(
|
290
|
+
CLIPSLexeme *value)
|
291
|
+
{
|
292
|
+
if (strcmp(value->contents,OBJECT_PATTERN_INDICATOR) == 0)
|
293
|
+
return true;
|
294
|
+
|
295
|
+
return false;
|
296
|
+
}
|
297
|
+
|
298
|
+
/************************************************************************************
|
299
|
+
NAME : ObjectLHSParse
|
300
|
+
DESCRIPTION : Scans and parses an object pattern for a rule
|
301
|
+
INPUTS : 1) The logical name of the input source
|
302
|
+
2) A buffer holding the last token read
|
303
|
+
RETURNS : The address of struct lhsParseNodes, NULL on errors
|
304
|
+
SIDE EFFECTS : A series of struct lhsParseNodes are created to represent
|
305
|
+
the intermediate parse of the pattern
|
306
|
+
Pretty-print form for the pattern is saved
|
307
|
+
NOTES : Object Pattern Syntax:
|
308
|
+
(object [<class-constraint>] [<name-constraint>] <slot-constraint>*)
|
309
|
+
<class-constraint> ::= (is-a <constraint>)
|
310
|
+
<name-constraint> ::= (name <constraint>)
|
311
|
+
<slot-constraint> ::= (<slot-name> <constraint>*)
|
312
|
+
************************************************************************************/
|
313
|
+
static struct lhsParseNode *ObjectLHSParse(
|
314
|
+
Environment *theEnv,
|
315
|
+
const char *readSource,
|
316
|
+
struct token *lastToken)
|
317
|
+
{
|
318
|
+
#if MAC_XCD
|
319
|
+
#pragma unused(lastToken)
|
320
|
+
#endif
|
321
|
+
struct token theToken;
|
322
|
+
struct lhsParseNode *firstNode = NULL,*lastNode = NULL,*tmpNode;
|
323
|
+
CLASS_BITMAP *clsset,*tmpset;
|
324
|
+
CONSTRAINT_RECORD *slotConstraints;
|
325
|
+
bool ppbackupReqd = false,multip;
|
326
|
+
|
327
|
+
/* ========================================================
|
328
|
+
Get a bitmap big enough to mark the ids of all currently
|
329
|
+
existing classes - and set all bits, since the initial
|
330
|
+
set of applicable classes is everything.
|
331
|
+
======================================================== */
|
332
|
+
clsset = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,true);
|
333
|
+
if (EmptyClassBitMap(clsset))
|
334
|
+
{
|
335
|
+
PrintErrorID(theEnv,"OBJRTBLD",1,false);
|
336
|
+
WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern.\n");
|
337
|
+
DeleteIntermediateClassBitMap(theEnv,clsset);
|
338
|
+
return NULL;
|
339
|
+
}
|
340
|
+
tmpset = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,true);
|
341
|
+
|
342
|
+
IncrementIndentDepth(theEnv,7);
|
343
|
+
|
344
|
+
/* ===========================================
|
345
|
+
Parse the class, name and slot restrictions
|
346
|
+
=========================================== */
|
347
|
+
GetToken(theEnv,readSource,&theToken);
|
348
|
+
while (theToken.tknType != RIGHT_PARENTHESIS_TOKEN)
|
349
|
+
{
|
350
|
+
ppbackupReqd = true;
|
351
|
+
PPBackup(theEnv);
|
352
|
+
SavePPBuffer(theEnv," ");
|
353
|
+
SavePPBuffer(theEnv,theToken.printForm);
|
354
|
+
if (theToken.tknType != LEFT_PARENTHESIS_TOKEN)
|
355
|
+
{
|
356
|
+
SyntaxErrorMessage(theEnv,"object pattern");
|
357
|
+
goto ObjectLHSParseERROR;
|
358
|
+
}
|
359
|
+
GetToken(theEnv,readSource,&theToken);
|
360
|
+
if (theToken.tknType != SYMBOL_TOKEN)
|
361
|
+
{
|
362
|
+
SyntaxErrorMessage(theEnv,"object pattern");
|
363
|
+
goto ObjectLHSParseERROR;
|
364
|
+
}
|
365
|
+
if (CheckDuplicateSlots(theEnv,firstNode,theToken.lexemeValue))
|
366
|
+
goto ObjectLHSParseERROR;
|
367
|
+
if (theToken.value == (void *) DefclassData(theEnv)->ISA_SYMBOL)
|
368
|
+
{
|
369
|
+
tmpNode = ParseClassRestriction(theEnv,readSource,&theToken);
|
370
|
+
if (tmpNode == NULL)
|
371
|
+
goto ObjectLHSParseERROR;
|
372
|
+
InitializeClassBitMap(theEnv,tmpset,false);
|
373
|
+
if (ProcessClassRestriction(theEnv,tmpset,&tmpNode->bottom,true) == false)
|
374
|
+
{
|
375
|
+
ReturnLHSParseNodes(theEnv,tmpNode);
|
376
|
+
goto ObjectLHSParseERROR;
|
377
|
+
}
|
378
|
+
IntersectClassBitMaps(clsset,tmpset);
|
379
|
+
}
|
380
|
+
else if (theToken.value == (void *) DefclassData(theEnv)->NAME_SYMBOL)
|
381
|
+
{
|
382
|
+
tmpNode = ParseNameRestriction(theEnv,readSource,&theToken);
|
383
|
+
if (tmpNode == NULL)
|
384
|
+
goto ObjectLHSParseERROR;
|
385
|
+
InitializeClassBitMap(theEnv,tmpset,true);
|
386
|
+
}
|
387
|
+
else
|
388
|
+
{
|
389
|
+
slotConstraints = ProcessSlotRestriction(theEnv,clsset,theToken.lexemeValue,&multip);
|
390
|
+
if (slotConstraints != NULL)
|
391
|
+
{
|
392
|
+
InitializeClassBitMap(theEnv,tmpset,true);
|
393
|
+
tmpNode = ParseSlotRestriction(theEnv,readSource,&theToken,slotConstraints,multip);
|
394
|
+
if (tmpNode == NULL)
|
395
|
+
goto ObjectLHSParseERROR;
|
396
|
+
}
|
397
|
+
else
|
398
|
+
{
|
399
|
+
InitializeClassBitMap(theEnv,tmpset,false);
|
400
|
+
tmpNode = GetLHSParseNode(theEnv);
|
401
|
+
tmpNode->slot = theToken.lexemeValue;
|
402
|
+
}
|
403
|
+
}
|
404
|
+
if (EmptyClassBitMap(tmpset))
|
405
|
+
{
|
406
|
+
PrintErrorID(theEnv,"OBJRTBLD",2,false);
|
407
|
+
WriteString(theEnv,STDERR,"No objects of existing classes can satisfy '");
|
408
|
+
WriteString(theEnv,STDERR,tmpNode->slot->contents);
|
409
|
+
WriteString(theEnv,STDERR,"' restriction in object pattern.\n");
|
410
|
+
ReturnLHSParseNodes(theEnv,tmpNode);
|
411
|
+
goto ObjectLHSParseERROR;
|
412
|
+
}
|
413
|
+
if (EmptyClassBitMap(clsset))
|
414
|
+
{
|
415
|
+
PrintErrorID(theEnv,"OBJRTBLD",1,false);
|
416
|
+
WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern.\n");
|
417
|
+
ReturnLHSParseNodes(theEnv,tmpNode);
|
418
|
+
goto ObjectLHSParseERROR;
|
419
|
+
}
|
420
|
+
if (tmpNode != NULL)
|
421
|
+
{
|
422
|
+
if (firstNode == NULL)
|
423
|
+
firstNode = tmpNode;
|
424
|
+
else
|
425
|
+
lastNode->right = tmpNode;
|
426
|
+
lastNode = tmpNode;
|
427
|
+
}
|
428
|
+
PPCRAndIndent(theEnv);
|
429
|
+
GetToken(theEnv,readSource,&theToken);
|
430
|
+
}
|
431
|
+
if (firstNode == NULL)
|
432
|
+
{
|
433
|
+
if (EmptyClassBitMap(clsset))
|
434
|
+
{
|
435
|
+
PrintErrorID(theEnv,"OBJRTBLD",1,false);
|
436
|
+
WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern.\n");
|
437
|
+
goto ObjectLHSParseERROR;
|
438
|
+
}
|
439
|
+
firstNode = GetLHSParseNode(theEnv);
|
440
|
+
firstNode->pnType = SF_WILDCARD_NODE;
|
441
|
+
firstNode->slot = DefclassData(theEnv)->ISA_SYMBOL;
|
442
|
+
firstNode->slotNumber = ISA_ID;
|
443
|
+
firstNode->index = 1;
|
444
|
+
}
|
445
|
+
if (ppbackupReqd)
|
446
|
+
{
|
447
|
+
PPBackup(theEnv);
|
448
|
+
PPBackup(theEnv);
|
449
|
+
SavePPBuffer(theEnv,theToken.printForm);
|
450
|
+
}
|
451
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset);
|
452
|
+
clsset = PackClassBitMap(theEnv,clsset);
|
453
|
+
firstNode->userData = AddBitMap(theEnv,clsset,ClassBitMapSize(clsset));
|
454
|
+
IncrementBitMapCount(firstNode->userData);
|
455
|
+
DeleteIntermediateClassBitMap(theEnv,clsset);
|
456
|
+
DecrementIndentDepth(theEnv,7);
|
457
|
+
return(firstNode);
|
458
|
+
|
459
|
+
ObjectLHSParseERROR:
|
460
|
+
DeleteIntermediateClassBitMap(theEnv,clsset);
|
461
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset);
|
462
|
+
ReturnLHSParseNodes(theEnv,firstNode);
|
463
|
+
DecrementIndentDepth(theEnv,7);
|
464
|
+
return NULL;
|
465
|
+
}
|
466
|
+
|
467
|
+
/**************************************************************
|
468
|
+
NAME : ReorderAndAnalyzeObjectPattern
|
469
|
+
DESCRIPTION : This function reexamines the object pattern
|
470
|
+
after constraint and variable analysis info
|
471
|
+
has been propagated from other patterns.
|
472
|
+
Any slots which are no longer applicable
|
473
|
+
to the pattern are eliminated from the
|
474
|
+
class set.
|
475
|
+
Also, the slot names are ordered according
|
476
|
+
to lexical value to aid in deteterming
|
477
|
+
sharing between object patterns. (The is-a
|
478
|
+
and name restrictions are always placed
|
479
|
+
first regardless of symbolic hash value.)
|
480
|
+
INPUTS : The pattern CE lhsParseNode
|
481
|
+
RETURNS : False if all OK, otherwise true
|
482
|
+
(e.g. all classes are eliminated as potential
|
483
|
+
matching candidates for the pattern)
|
484
|
+
SIDE EFFECTS : Slot restrictions are reordered (if necessary)
|
485
|
+
NOTES : Adds a default is-a slot if one does not
|
486
|
+
already exist
|
487
|
+
**************************************************************/
|
488
|
+
static bool ReorderAndAnalyzeObjectPattern(
|
489
|
+
Environment *theEnv,
|
490
|
+
struct lhsParseNode *topNode)
|
491
|
+
{
|
492
|
+
const CLASS_BITMAP *clsset;
|
493
|
+
CLASS_BITMAP *tmpset;
|
494
|
+
Expression *rexp,*tmpmin,*tmpmax;
|
495
|
+
Defclass *cls;
|
496
|
+
struct lhsParseNode *tmpNode,*subNode,*bitmap_node,*isa_node,*name_node;
|
497
|
+
unsigned short i;
|
498
|
+
SlotDescriptor *sd;
|
499
|
+
CONSTRAINT_RECORD *crossConstraints, *theConstraint;
|
500
|
+
int incompatibleConstraint;
|
501
|
+
bool clssetChanged = false;
|
502
|
+
|
503
|
+
/* ==========================================================
|
504
|
+
Make sure that the bitmap marking which classes of object
|
505
|
+
can match the pattern is attached to the class restriction
|
506
|
+
(which will always be present and the last restriction
|
507
|
+
after the sort)
|
508
|
+
========================================================== */
|
509
|
+
topNode->right = FilterObjectPattern(theEnv,topNode->patternType,topNode->right,
|
510
|
+
&bitmap_node,&isa_node,&name_node);
|
511
|
+
|
512
|
+
/* ============================================
|
513
|
+
Allocate a temporary set for marking classes
|
514
|
+
============================================ */
|
515
|
+
clsset = (const CLASS_BITMAP *) ((CLIPSBitMap *) bitmap_node->userData)->contents;
|
516
|
+
tmpset = NewClassBitMap(theEnv,clsset->maxid,false);
|
517
|
+
|
518
|
+
/* ==========================================================
|
519
|
+
Check the allowed-values for the constraint on the is-a
|
520
|
+
slot. If there are any, make sure that only the classes
|
521
|
+
with those values as names are marked in the bitmap.
|
522
|
+
|
523
|
+
There will only be symbols in the list because the
|
524
|
+
original constraint on the is-a slot allowed only symbols.
|
525
|
+
========================================================== */
|
526
|
+
if ((isa_node == NULL) ? false :
|
527
|
+
((isa_node->constraints == NULL) ? false :
|
528
|
+
(isa_node->constraints->restrictionList != NULL)))
|
529
|
+
{
|
530
|
+
rexp = isa_node->constraints->restrictionList;
|
531
|
+
while (rexp != NULL)
|
532
|
+
{
|
533
|
+
cls = LookupDefclassInScope(theEnv,rexp->lexemeValue->contents);
|
534
|
+
if (cls != NULL)
|
535
|
+
{
|
536
|
+
if ((cls->id <= clsset->maxid) ? TestBitMap(clsset->map,cls->id) : false)
|
537
|
+
SetBitMap(tmpset->map,cls->id);
|
538
|
+
}
|
539
|
+
rexp = rexp->nextArg;
|
540
|
+
}
|
541
|
+
clssetChanged = IdenticalClassBitMap(tmpset,clsset) ? false : true;
|
542
|
+
}
|
543
|
+
else
|
544
|
+
GenCopyMemory(char,tmpset->maxid / BITS_PER_BYTE + 1,tmpset->map,clsset->map);
|
545
|
+
|
546
|
+
/* ================================================================
|
547
|
+
For each of the slots (excluding name and is-a), check the total
|
548
|
+
constraints for the slot against the individual constraints
|
549
|
+
for each occurrence of the slot in the classes marked in
|
550
|
+
the bitmap. For any slot which is not compatible with
|
551
|
+
the overall constraint, clear its class's bit in the bitmap.
|
552
|
+
================================================================ */
|
553
|
+
tmpNode = topNode->right;
|
554
|
+
while (tmpNode != bitmap_node)
|
555
|
+
{
|
556
|
+
if ((tmpNode == isa_node) || (tmpNode == name_node))
|
557
|
+
{
|
558
|
+
tmpNode = tmpNode->right;
|
559
|
+
continue;
|
560
|
+
}
|
561
|
+
for (i = 0 ; i <= tmpset->maxid ; i++)
|
562
|
+
if (TestBitMap(tmpset->map,i))
|
563
|
+
{
|
564
|
+
cls = DefclassData(theEnv)->ClassIDMap[i];
|
565
|
+
sd = cls->instanceTemplate[FindInstanceTemplateSlot(theEnv,cls,tmpNode->slot)];
|
566
|
+
|
567
|
+
/* =========================================
|
568
|
+
Check the top-level lhsParseNode for type
|
569
|
+
and cardinality compatibility
|
570
|
+
========================================= */
|
571
|
+
crossConstraints = IntersectConstraints(theEnv,tmpNode->constraints,sd->constraint);
|
572
|
+
incompatibleConstraint = UnmatchableConstraint(crossConstraints);
|
573
|
+
RemoveConstraint(theEnv,crossConstraints);
|
574
|
+
if (incompatibleConstraint)
|
575
|
+
{
|
576
|
+
ClearBitMap(tmpset->map,i);
|
577
|
+
clssetChanged = true;
|
578
|
+
}
|
579
|
+
else if (tmpNode->pnType == MF_WILDCARD_NODE)
|
580
|
+
{
|
581
|
+
/* ==========================================
|
582
|
+
Check the sub-nodes for type compatibility
|
583
|
+
========================================== */
|
584
|
+
for (subNode = tmpNode->bottom ; subNode != NULL ; subNode = subNode->right)
|
585
|
+
{
|
586
|
+
/* ========================================================
|
587
|
+
Temporarily reset cardinality of variables to
|
588
|
+
match slot so that no cardinality errors will be flagged
|
589
|
+
======================================================== */
|
590
|
+
if ((subNode->pnType == MF_WILDCARD_NODE) || (subNode->pnType == MF_VARIABLE_NODE))
|
591
|
+
{ theConstraint = subNode->constraints->multifield; }
|
592
|
+
else
|
593
|
+
{ theConstraint = subNode->constraints; }
|
594
|
+
|
595
|
+
tmpmin = theConstraint->minFields;
|
596
|
+
theConstraint->minFields = sd->constraint->minFields;
|
597
|
+
tmpmax = theConstraint->maxFields;
|
598
|
+
theConstraint->maxFields = sd->constraint->maxFields;
|
599
|
+
crossConstraints = IntersectConstraints(theEnv,theConstraint,sd->constraint);
|
600
|
+
theConstraint->minFields = tmpmin;
|
601
|
+
theConstraint->maxFields = tmpmax;
|
602
|
+
|
603
|
+
incompatibleConstraint = UnmatchableConstraint(crossConstraints);
|
604
|
+
RemoveConstraint(theEnv,crossConstraints);
|
605
|
+
if (incompatibleConstraint)
|
606
|
+
{
|
607
|
+
ClearBitMap(tmpset->map,i);
|
608
|
+
clssetChanged = true;
|
609
|
+
break;
|
610
|
+
}
|
611
|
+
}
|
612
|
+
}
|
613
|
+
}
|
614
|
+
tmpNode = tmpNode->right;
|
615
|
+
}
|
616
|
+
|
617
|
+
if (clssetChanged)
|
618
|
+
{
|
619
|
+
/* =======================================================
|
620
|
+
Make sure that there are still classes of objects which
|
621
|
+
can satisfy this pattern. Otherwise, signal an error.
|
622
|
+
======================================================= */
|
623
|
+
if (EmptyClassBitMap(tmpset))
|
624
|
+
{
|
625
|
+
PrintErrorID(theEnv,"OBJRTBLD",3,true);
|
626
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset);
|
627
|
+
WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern #");
|
628
|
+
WriteInteger(theEnv,STDERR,topNode->pattern);
|
629
|
+
WriteString(theEnv,STDERR,".\n");
|
630
|
+
return true;
|
631
|
+
}
|
632
|
+
clsset = PackClassBitMap(theEnv,tmpset);
|
633
|
+
DeleteClassBitMap(theEnv,bitmap_node->userData);
|
634
|
+
bitmap_node->userData = AddBitMap(theEnv,(void *) clsset,ClassBitMapSize(clsset));
|
635
|
+
IncrementBitMapCount(bitmap_node->userData);
|
636
|
+
DeleteIntermediateClassBitMap(theEnv,clsset);
|
637
|
+
}
|
638
|
+
else
|
639
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset);
|
640
|
+
return false;
|
641
|
+
}
|
642
|
+
|
643
|
+
/*****************************************************
|
644
|
+
NAME : PlaceObjectPattern
|
645
|
+
DESCRIPTION : Integrates an object pattern into the
|
646
|
+
object pattern network
|
647
|
+
INPUTS : The intermediate parse representation
|
648
|
+
of the pattern
|
649
|
+
RETURNS : The address of the new pattern
|
650
|
+
SIDE EFFECTS : Object pattern network updated
|
651
|
+
NOTES : None
|
652
|
+
*****************************************************/
|
653
|
+
static struct patternNodeHeader *PlaceObjectPattern(
|
654
|
+
Environment *theEnv,
|
655
|
+
struct lhsParseNode *thePattern)
|
656
|
+
{
|
657
|
+
OBJECT_PATTERN_NODE *currentLevel,*lastLevel;
|
658
|
+
struct lhsParseNode *tempPattern = NULL;
|
659
|
+
OBJECT_PATTERN_NODE *nodeSlotGroup, *newNode;
|
660
|
+
OBJECT_ALPHA_NODE *newAlphaNode;
|
661
|
+
bool endSlot;
|
662
|
+
CLIPSBitMap *newClassBitMap,*newSlotBitMap;
|
663
|
+
struct expr *rightHash;
|
664
|
+
unsigned int i;
|
665
|
+
const CLASS_BITMAP *cbmp;
|
666
|
+
Defclass *relevantDefclass;
|
667
|
+
CLASS_ALPHA_LINK *newAlphaLink;
|
668
|
+
|
669
|
+
/*========================================================*/
|
670
|
+
/* Get the top of the object pattern network and prepare */
|
671
|
+
/* for the traversal to look for shareable pattern nodes. */
|
672
|
+
/*========================================================*/
|
673
|
+
|
674
|
+
currentLevel = ObjectNetworkPointer(theEnv);
|
675
|
+
lastLevel = NULL;
|
676
|
+
|
677
|
+
/*====================================================*/
|
678
|
+
/* Remove slot existence tests from the pattern since */
|
679
|
+
/* these are accounted for by the class bitmap and */
|
680
|
+
/* find the class and slot bitmaps. */
|
681
|
+
/*====================================================*/
|
682
|
+
|
683
|
+
rightHash = thePattern->rightHash;
|
684
|
+
|
685
|
+
newSlotBitMap = FormSlotBitMap(theEnv,thePattern->right);
|
686
|
+
thePattern->right = RemoveSlotExistenceTests(theEnv,thePattern->right,&newClassBitMap);
|
687
|
+
thePattern = thePattern->right;
|
688
|
+
|
689
|
+
/*=========================================================*/
|
690
|
+
/* Loop until all fields in the pattern have been added to */
|
691
|
+
/* the pattern network. Process the bitmap node ONLY if it */
|
692
|
+
/* is the only node in the pattern. */
|
693
|
+
/*=========================================================*/
|
694
|
+
|
695
|
+
do
|
696
|
+
{
|
697
|
+
if (thePattern->multifieldSlot)
|
698
|
+
{
|
699
|
+
tempPattern = thePattern;
|
700
|
+
thePattern = thePattern->bottom;
|
701
|
+
}
|
702
|
+
|
703
|
+
/*============================================*/
|
704
|
+
/* Determine if the last pattern field within */
|
705
|
+
/* a multifield slot is being processed. */
|
706
|
+
/*============================================*/
|
707
|
+
|
708
|
+
if (((thePattern->pnType == MF_WILDCARD_NODE) ||
|
709
|
+
(thePattern->pnType == MF_VARIABLE_NODE)) &&
|
710
|
+
(thePattern->right == NULL) && (tempPattern != NULL))
|
711
|
+
{ endSlot = true; }
|
712
|
+
else
|
713
|
+
{ endSlot = false; }
|
714
|
+
|
715
|
+
/*========================================*/
|
716
|
+
/* Is there a node in the pattern network */
|
717
|
+
/* that can be reused (shared)? */
|
718
|
+
/*========================================*/
|
719
|
+
|
720
|
+
newNode = FindObjectPatternNode(currentLevel,thePattern,&nodeSlotGroup,endSlot,false);
|
721
|
+
|
722
|
+
/*================================================*/
|
723
|
+
/* If the pattern node cannot be shared, then add */
|
724
|
+
/* a new pattern node to the pattern network. */
|
725
|
+
/*================================================*/
|
726
|
+
|
727
|
+
if (newNode == NULL)
|
728
|
+
{ newNode = CreateNewObjectPatternNode(theEnv,thePattern,nodeSlotGroup,lastLevel,endSlot,false); }
|
729
|
+
|
730
|
+
if (thePattern->constantSelector != NULL)
|
731
|
+
{
|
732
|
+
currentLevel = newNode->nextLevel;
|
733
|
+
lastLevel = newNode;
|
734
|
+
newNode = FindObjectPatternNode(currentLevel,thePattern,&nodeSlotGroup,endSlot,true);
|
735
|
+
|
736
|
+
if (newNode == NULL)
|
737
|
+
{ newNode = CreateNewObjectPatternNode(theEnv,thePattern,nodeSlotGroup,lastLevel,endSlot,true); }
|
738
|
+
}
|
739
|
+
|
740
|
+
/*=======================================================*/
|
741
|
+
/* Move on to the next field in the pattern to be added. */
|
742
|
+
/*=======================================================*/
|
743
|
+
|
744
|
+
if ((thePattern->right == NULL) && (tempPattern != NULL))
|
745
|
+
{
|
746
|
+
thePattern = tempPattern;
|
747
|
+
tempPattern = NULL;
|
748
|
+
}
|
749
|
+
|
750
|
+
lastLevel = newNode;
|
751
|
+
currentLevel = newNode->nextLevel;
|
752
|
+
thePattern = thePattern->right;
|
753
|
+
}
|
754
|
+
while ((thePattern != NULL) ? (thePattern->userData == NULL) : false);
|
755
|
+
|
756
|
+
/*==================================================*/
|
757
|
+
/* Return the leaf node of the newly added pattern. */
|
758
|
+
/*==================================================*/
|
759
|
+
|
760
|
+
newAlphaNode = lastLevel->alphaNode;
|
761
|
+
while (newAlphaNode != NULL)
|
762
|
+
{
|
763
|
+
if ((newClassBitMap == newAlphaNode->classbmp) &&
|
764
|
+
(newSlotBitMap == newAlphaNode->slotbmp) &&
|
765
|
+
IdenticalExpression(newAlphaNode->header.rightHash,rightHash))
|
766
|
+
return((struct patternNodeHeader *) newAlphaNode);
|
767
|
+
newAlphaNode = newAlphaNode->nxtInGroup;
|
768
|
+
}
|
769
|
+
|
770
|
+
newAlphaNode = get_struct(theEnv,objectAlphaNode);
|
771
|
+
InitializePatternHeader(theEnv,&newAlphaNode->header);
|
772
|
+
newAlphaNode->header.rightHash = AddHashedExpression(theEnv,rightHash);
|
773
|
+
newAlphaNode->matchTimeTag = 0L;
|
774
|
+
newAlphaNode->patternNode = lastLevel;
|
775
|
+
newAlphaNode->classbmp = newClassBitMap;
|
776
|
+
IncrementBitMapCount(newClassBitMap);
|
777
|
+
MarkBitMapClassesBusy(theEnv,newClassBitMap,1);
|
778
|
+
newAlphaNode->slotbmp = newSlotBitMap;
|
779
|
+
if (newSlotBitMap != NULL)
|
780
|
+
IncrementBitMapCount(newSlotBitMap);
|
781
|
+
newAlphaNode->bsaveID = 0L;
|
782
|
+
newAlphaNode->nxtInGroup = lastLevel->alphaNode;
|
783
|
+
lastLevel->alphaNode = newAlphaNode;
|
784
|
+
newAlphaNode->nxtTerminal = ObjectNetworkTerminalPointer(theEnv);
|
785
|
+
SetObjectNetworkTerminalPointer(theEnv,newAlphaNode);
|
786
|
+
|
787
|
+
/*
|
788
|
+
* A new terminal alpha node has just been created. For each defclass
|
789
|
+
* relevant to this alpha node, add it to that defclass'
|
790
|
+
* relevant_terminal_alpha_nodes list
|
791
|
+
*/
|
792
|
+
cbmp = (const CLASS_BITMAP *) newClassBitMap->contents;
|
793
|
+
for (i = 0; i <= cbmp->maxid; i++)
|
794
|
+
{
|
795
|
+
if (TestBitMap(cbmp->map,i))
|
796
|
+
{
|
797
|
+
relevantDefclass = DefclassData(theEnv)->ClassIDMap[i];
|
798
|
+
newAlphaLink = get_struct(theEnv, classAlphaLink);
|
799
|
+
newAlphaLink->alphaNode = newAlphaNode;
|
800
|
+
newAlphaLink->next = relevantDefclass->relevant_terminal_alpha_nodes;
|
801
|
+
relevantDefclass->relevant_terminal_alpha_nodes = newAlphaLink;
|
802
|
+
}
|
803
|
+
}
|
804
|
+
|
805
|
+
return((struct patternNodeHeader *) newAlphaNode);
|
806
|
+
}
|
807
|
+
|
808
|
+
/************************************************************************
|
809
|
+
NAME : FindObjectPatternNode
|
810
|
+
DESCRIPTION : Looks for a pattern node at a specified
|
811
|
+
level in the pattern network that can be reused (shared)
|
812
|
+
with a pattern field being added to the pattern network.
|
813
|
+
INPUTS : 1) The current layer of nodes being examined in the
|
814
|
+
object pattern network
|
815
|
+
2) The intermediate parse representation of the pattern
|
816
|
+
being added
|
817
|
+
3) A buffer for holding the first node of a group
|
818
|
+
of slots with the same name as the new node
|
819
|
+
4) An integer code indicating if this is the last
|
820
|
+
fiedl in a slot pattern or not
|
821
|
+
RETURNS : The old pattern network node matching the new node, or
|
822
|
+
NULL if there is none (nodeSlotGroup will hold the
|
823
|
+
place where to attach a new node)
|
824
|
+
SIDE EFFECTS : nodeSlotGroup set
|
825
|
+
NOTES : None
|
826
|
+
************************************************************************/
|
827
|
+
static OBJECT_PATTERN_NODE *FindObjectPatternNode(
|
828
|
+
OBJECT_PATTERN_NODE *listOfNodes,
|
829
|
+
struct lhsParseNode *thePattern,
|
830
|
+
OBJECT_PATTERN_NODE **nodeSlotGroup,
|
831
|
+
bool endSlot,
|
832
|
+
bool constantSelector)
|
833
|
+
{
|
834
|
+
struct expr *compareTest;
|
835
|
+
*nodeSlotGroup = NULL;
|
836
|
+
|
837
|
+
if (constantSelector)
|
838
|
+
{ compareTest = thePattern->constantValue; }
|
839
|
+
else if (thePattern->constantSelector != NULL)
|
840
|
+
{ compareTest = thePattern->constantSelector; }
|
841
|
+
else
|
842
|
+
{ compareTest = thePattern->networkTest; }
|
843
|
+
|
844
|
+
/*==========================================================*/
|
845
|
+
/* Loop through the nodes at the given level in the pattern */
|
846
|
+
/* network looking for a node that can be reused (shared). */
|
847
|
+
/*==========================================================*/
|
848
|
+
|
849
|
+
while (listOfNodes != NULL)
|
850
|
+
{
|
851
|
+
/*=========================================================*/
|
852
|
+
/* A object pattern node can be shared if the slot name is */
|
853
|
+
/* the same, the test is on the same field in the pattern, */
|
854
|
+
/* and the network test expressions are the same. */
|
855
|
+
/*=========================================================*/
|
856
|
+
|
857
|
+
if (((thePattern->pnType == MF_WILDCARD_NODE) || (thePattern->pnType == MF_VARIABLE_NODE)) ?
|
858
|
+
listOfNodes->multifieldNode : (listOfNodes->multifieldNode == 0))
|
859
|
+
{
|
860
|
+
if ((thePattern->slotNumber == listOfNodes->slotNameID) &&
|
861
|
+
(thePattern->index == listOfNodes->whichField) &&
|
862
|
+
(thePattern->singleFieldsAfter == listOfNodes->leaveFields) &&
|
863
|
+
(endSlot == listOfNodes->endSlot) &&
|
864
|
+
IdenticalExpression(listOfNodes->networkTest,compareTest))
|
865
|
+
return(listOfNodes);
|
866
|
+
}
|
867
|
+
|
868
|
+
/*===============================================*/
|
869
|
+
/* Find the beginning of a group of nodes with */
|
870
|
+
/* the same slot name testing on the same field. */
|
871
|
+
/*===============================================*/
|
872
|
+
|
873
|
+
if ((*nodeSlotGroup == NULL) &&
|
874
|
+
(thePattern->index == listOfNodes->whichField) &&
|
875
|
+
(thePattern->slotNumber == listOfNodes->slotNameID))
|
876
|
+
*nodeSlotGroup = listOfNodes;
|
877
|
+
listOfNodes = listOfNodes->rightNode;
|
878
|
+
}
|
879
|
+
|
880
|
+
/*==============================================*/
|
881
|
+
/* A shareable pattern node could not be found. */
|
882
|
+
/*==============================================*/
|
883
|
+
|
884
|
+
return NULL;
|
885
|
+
}
|
886
|
+
|
887
|
+
/*****************************************************************
|
888
|
+
NAME : CreateNewObjectPatternNode
|
889
|
+
DESCRIPTION : Creates a new pattern node and initializes
|
890
|
+
all of its values.
|
891
|
+
INPUTS : 1) The intermediate parse representation
|
892
|
+
of the new pattern node
|
893
|
+
2) A pointer to the network node after
|
894
|
+
which to add the new node
|
895
|
+
3) A pointer to the parent node on the
|
896
|
+
level above to link the new node
|
897
|
+
4) An integer code indicating if this is the last
|
898
|
+
fiedl in a slot pattern or not
|
899
|
+
RETURNS : A pointer to the new pattern node
|
900
|
+
SIDE EFFECTS : Pattern node allocated, initialized and
|
901
|
+
attached
|
902
|
+
NOTES : None
|
903
|
+
*****************************************************************/
|
904
|
+
static OBJECT_PATTERN_NODE *CreateNewObjectPatternNode(
|
905
|
+
Environment *theEnv,
|
906
|
+
struct lhsParseNode *thePattern,
|
907
|
+
OBJECT_PATTERN_NODE *nodeSlotGroup,
|
908
|
+
OBJECT_PATTERN_NODE *upperLevel,
|
909
|
+
bool endSlot,
|
910
|
+
bool constantSelector)
|
911
|
+
{
|
912
|
+
OBJECT_PATTERN_NODE *newNode,*prvNode,*curNode;
|
913
|
+
|
914
|
+
newNode = get_struct(theEnv,objectPatternNode);
|
915
|
+
newNode->blocked = false;
|
916
|
+
newNode->multifieldNode = false;
|
917
|
+
newNode->alphaNode = NULL;
|
918
|
+
newNode->matchTimeTag = 0L;
|
919
|
+
newNode->nextLevel = NULL;
|
920
|
+
newNode->rightNode = NULL;
|
921
|
+
newNode->leftNode = NULL;
|
922
|
+
newNode->bsaveID = 0L;
|
923
|
+
|
924
|
+
if ((thePattern->constantSelector != NULL) && (! constantSelector))
|
925
|
+
{ newNode->selector = true; }
|
926
|
+
else
|
927
|
+
{ newNode->selector = false; }
|
928
|
+
|
929
|
+
/*===========================================================*/
|
930
|
+
/* Install the expression associated with this pattern node. */
|
931
|
+
/*===========================================================*/
|
932
|
+
|
933
|
+
if (constantSelector)
|
934
|
+
{ newNode->networkTest = AddHashedExpression(theEnv,thePattern->constantValue); }
|
935
|
+
else if (thePattern->constantSelector != NULL)
|
936
|
+
{ newNode->networkTest = AddHashedExpression(theEnv,thePattern->constantSelector); }
|
937
|
+
else
|
938
|
+
{ newNode->networkTest = AddHashedExpression(theEnv,thePattern->networkTest); }
|
939
|
+
|
940
|
+
newNode->whichField = thePattern->index;
|
941
|
+
newNode->leaveFields = thePattern->singleFieldsAfter;
|
942
|
+
|
943
|
+
/*=========================================*/
|
944
|
+
/* Install the slot name for the new node. */
|
945
|
+
/*=========================================*/
|
946
|
+
|
947
|
+
newNode->slotNameID = thePattern->slotNumber;
|
948
|
+
if ((thePattern->pnType == MF_WILDCARD_NODE) || (thePattern->pnType == MF_VARIABLE_NODE))
|
949
|
+
newNode->multifieldNode = true;
|
950
|
+
newNode->endSlot = endSlot;
|
951
|
+
|
952
|
+
/*===============================================*/
|
953
|
+
/* Set the upper level pointer for the new node. */
|
954
|
+
/*===============================================*/
|
955
|
+
|
956
|
+
newNode->lastLevel = upperLevel;
|
957
|
+
|
958
|
+
if ((upperLevel != NULL) && (upperLevel->selector))
|
959
|
+
{ AddHashedPatternNode(theEnv,upperLevel,newNode,newNode->networkTest->type,newNode->networkTest->value); }
|
960
|
+
|
961
|
+
/*==============================================*/
|
962
|
+
/* If there are no nodes with this slot name on */
|
963
|
+
/* this level, simply prepend it to the front. */
|
964
|
+
/*==============================================*/
|
965
|
+
|
966
|
+
if (nodeSlotGroup == NULL)
|
967
|
+
{
|
968
|
+
if (upperLevel == NULL)
|
969
|
+
{
|
970
|
+
newNode->rightNode = ObjectNetworkPointer(theEnv);
|
971
|
+
SetObjectNetworkPointer(theEnv,newNode);
|
972
|
+
}
|
973
|
+
else
|
974
|
+
{
|
975
|
+
newNode->rightNode = upperLevel->nextLevel;
|
976
|
+
upperLevel->nextLevel = newNode;
|
977
|
+
}
|
978
|
+
if (newNode->rightNode != NULL)
|
979
|
+
newNode->rightNode->leftNode = newNode;
|
980
|
+
return(newNode);
|
981
|
+
}
|
982
|
+
|
983
|
+
/* ===========================================================
|
984
|
+
Group this node with other nodes of the same name
|
985
|
+
testing on the same field in the pattern
|
986
|
+
on this level. This allows us to do some optimization
|
987
|
+
with constant tests on a particular slots. If we put
|
988
|
+
all constant tests for a particular slot/field group at the
|
989
|
+
end of that group, then when one of those test succeeds
|
990
|
+
during pattern-matching, we don't have to test any
|
991
|
+
more of the nodes with that slot/field name to the right.
|
992
|
+
=========================================================== */
|
993
|
+
prvNode = NULL;
|
994
|
+
curNode = nodeSlotGroup;
|
995
|
+
while ((curNode == NULL) ? false :
|
996
|
+
(curNode->slotNameID == nodeSlotGroup->slotNameID) &&
|
997
|
+
(curNode->whichField == nodeSlotGroup->whichField))
|
998
|
+
{
|
999
|
+
if ((curNode->networkTest == NULL) ? false :
|
1000
|
+
((curNode->networkTest->type != OBJ_PN_CONSTANT) ? false :
|
1001
|
+
((const struct ObjectCmpPNConstant *) curNode->networkTest->bitMapValue->contents)->pass))
|
1002
|
+
break;
|
1003
|
+
prvNode = curNode;
|
1004
|
+
curNode = curNode->rightNode;
|
1005
|
+
}
|
1006
|
+
if (curNode != NULL)
|
1007
|
+
{
|
1008
|
+
newNode->leftNode = curNode->leftNode;
|
1009
|
+
newNode->rightNode = curNode;
|
1010
|
+
if (curNode->leftNode != NULL)
|
1011
|
+
curNode->leftNode->rightNode = newNode;
|
1012
|
+
else if (curNode->lastLevel != NULL)
|
1013
|
+
curNode->lastLevel->nextLevel = newNode;
|
1014
|
+
else
|
1015
|
+
SetObjectNetworkPointer(theEnv,newNode);
|
1016
|
+
curNode->leftNode = newNode;
|
1017
|
+
}
|
1018
|
+
else
|
1019
|
+
{
|
1020
|
+
newNode->leftNode = prvNode;
|
1021
|
+
prvNode->rightNode = newNode;
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
return(newNode);
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
/********************************************************
|
1028
|
+
NAME : DetachObjectPattern
|
1029
|
+
DESCRIPTION : Removes a pattern node and all of its
|
1030
|
+
parent nodes from the pattern network. Nodes are only
|
1031
|
+
removed if they are no longer shared (i.e. a pattern
|
1032
|
+
node that has more than one child node is shared). A
|
1033
|
+
pattern from a rule is typically removed by removing
|
1034
|
+
the bottom most pattern node used by the pattern and
|
1035
|
+
then removing any parent nodes which are not shared by
|
1036
|
+
other patterns.
|
1037
|
+
|
1038
|
+
Example:
|
1039
|
+
Patterns (a b c d) and (a b e f) would be represented
|
1040
|
+
by the pattern net shown on the left. If (a b c d)
|
1041
|
+
was detached, the resultant pattern net would be the
|
1042
|
+
one shown on the right. The '=' represents an
|
1043
|
+
end-of-pattern node.
|
1044
|
+
|
1045
|
+
a a
|
1046
|
+
| |
|
1047
|
+
b b
|
1048
|
+
| |
|
1049
|
+
c--e e
|
1050
|
+
| | |
|
1051
|
+
d f f
|
1052
|
+
| | |
|
1053
|
+
= = =
|
1054
|
+
INPUTS : The pattern to be removed
|
1055
|
+
RETURNS : Nothing useful
|
1056
|
+
SIDE EFFECTS : All non-shared nodes associated with the
|
1057
|
+
pattern are removed
|
1058
|
+
NOTES : None
|
1059
|
+
********************************************************/
|
1060
|
+
static void DetachObjectPattern(
|
1061
|
+
Environment *theEnv,
|
1062
|
+
struct patternNodeHeader *thePattern)
|
1063
|
+
{
|
1064
|
+
OBJECT_ALPHA_NODE *alphaPtr,*prv,*terminalPtr;
|
1065
|
+
OBJECT_PATTERN_NODE *patternPtr,*upperLevel;
|
1066
|
+
|
1067
|
+
/*====================================================*/
|
1068
|
+
/* Get rid of any matches stored in the alpha memory. */
|
1069
|
+
/*====================================================*/
|
1070
|
+
|
1071
|
+
alphaPtr = (OBJECT_ALPHA_NODE *) thePattern;
|
1072
|
+
ClearObjectPatternMatches(theEnv,alphaPtr);
|
1073
|
+
|
1074
|
+
/*==================================*/
|
1075
|
+
/* Remove alpha links from classes. */
|
1076
|
+
/*==================================*/
|
1077
|
+
|
1078
|
+
if (! ConstructData(theEnv)->ClearInProgress)
|
1079
|
+
{
|
1080
|
+
const CLASS_BITMAP *cbmp;
|
1081
|
+
unsigned int i;
|
1082
|
+
Defclass *relevantDefclass;
|
1083
|
+
CLASS_ALPHA_LINK *alphaLink, *lastAlpha;
|
1084
|
+
|
1085
|
+
cbmp = (const CLASS_BITMAP *) alphaPtr->classbmp->contents;
|
1086
|
+
for (i = 0; i <= cbmp->maxid; i++)
|
1087
|
+
{
|
1088
|
+
if (TestBitMap(cbmp->map,i))
|
1089
|
+
{
|
1090
|
+
relevantDefclass = DefclassData(theEnv)->ClassIDMap[i];
|
1091
|
+
|
1092
|
+
for (lastAlpha = NULL, alphaLink = relevantDefclass->relevant_terminal_alpha_nodes;
|
1093
|
+
alphaLink != NULL;
|
1094
|
+
lastAlpha = alphaLink, alphaLink = alphaLink->next)
|
1095
|
+
{
|
1096
|
+
if (alphaLink->alphaNode == alphaPtr)
|
1097
|
+
{
|
1098
|
+
if (lastAlpha == NULL)
|
1099
|
+
{ relevantDefclass->relevant_terminal_alpha_nodes = alphaLink->next; }
|
1100
|
+
else
|
1101
|
+
{ lastAlpha->next = alphaLink->next; }
|
1102
|
+
rtn_struct(theEnv,classAlphaLink,alphaLink);
|
1103
|
+
break;
|
1104
|
+
}
|
1105
|
+
}
|
1106
|
+
}
|
1107
|
+
}
|
1108
|
+
}
|
1109
|
+
|
1110
|
+
/*========================================================*/
|
1111
|
+
/* Unmark the classes to which the pattern is applicable */
|
1112
|
+
/* and unmark the class and slot id maps so that they can */
|
1113
|
+
/* become ephemeral. */
|
1114
|
+
/*========================================================*/
|
1115
|
+
|
1116
|
+
MarkBitMapClassesBusy(theEnv,alphaPtr->classbmp,-1);
|
1117
|
+
DeleteClassBitMap(theEnv,alphaPtr->classbmp);
|
1118
|
+
if (alphaPtr->slotbmp != NULL)
|
1119
|
+
{ DecrementBitMapReferenceCount(theEnv,alphaPtr->slotbmp); }
|
1120
|
+
|
1121
|
+
/*=========================================*/
|
1122
|
+
/* Only continue deleting this pattern if */
|
1123
|
+
/* this is the last alpha memory attached. */
|
1124
|
+
/*=========================================*/
|
1125
|
+
|
1126
|
+
prv = NULL;
|
1127
|
+
terminalPtr = ObjectNetworkTerminalPointer(theEnv);
|
1128
|
+
while (terminalPtr != alphaPtr)
|
1129
|
+
{
|
1130
|
+
prv = terminalPtr;
|
1131
|
+
terminalPtr = terminalPtr->nxtTerminal;
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
if (prv == NULL)
|
1135
|
+
{ SetObjectNetworkTerminalPointer(theEnv,terminalPtr->nxtTerminal); }
|
1136
|
+
else
|
1137
|
+
{ prv->nxtTerminal = terminalPtr->nxtTerminal; }
|
1138
|
+
|
1139
|
+
prv = NULL;
|
1140
|
+
terminalPtr = alphaPtr->patternNode->alphaNode;
|
1141
|
+
while (terminalPtr != alphaPtr)
|
1142
|
+
{
|
1143
|
+
prv = terminalPtr;
|
1144
|
+
terminalPtr = terminalPtr->nxtInGroup;
|
1145
|
+
}
|
1146
|
+
|
1147
|
+
if (prv == NULL)
|
1148
|
+
{
|
1149
|
+
if (alphaPtr->nxtInGroup != NULL)
|
1150
|
+
{
|
1151
|
+
alphaPtr->patternNode->alphaNode = alphaPtr->nxtInGroup;
|
1152
|
+
RemoveHashedExpression(theEnv,alphaPtr->header.rightHash);
|
1153
|
+
rtn_struct(theEnv,objectAlphaNode,alphaPtr);
|
1154
|
+
return;
|
1155
|
+
}
|
1156
|
+
}
|
1157
|
+
else
|
1158
|
+
{
|
1159
|
+
prv->nxtInGroup = alphaPtr->nxtInGroup;
|
1160
|
+
RemoveHashedExpression(theEnv,alphaPtr->header.rightHash);
|
1161
|
+
rtn_struct(theEnv,objectAlphaNode,alphaPtr);
|
1162
|
+
return;
|
1163
|
+
}
|
1164
|
+
alphaPtr->patternNode->alphaNode = NULL;
|
1165
|
+
RemoveHashedExpression(theEnv,alphaPtr->header.rightHash);
|
1166
|
+
upperLevel = alphaPtr->patternNode;
|
1167
|
+
rtn_struct(theEnv,objectAlphaNode,alphaPtr);
|
1168
|
+
|
1169
|
+
if (upperLevel->nextLevel != NULL)
|
1170
|
+
return;
|
1171
|
+
|
1172
|
+
/*==============================================================*/
|
1173
|
+
/* Loop until all appropriate pattern nodes have been detached. */
|
1174
|
+
/*==============================================================*/
|
1175
|
+
|
1176
|
+
while (upperLevel != NULL)
|
1177
|
+
{
|
1178
|
+
if ((upperLevel->leftNode == NULL) &&
|
1179
|
+
(upperLevel->rightNode == NULL))
|
1180
|
+
{
|
1181
|
+
/*===============================================*/
|
1182
|
+
/* Pattern node is the only node on this level. */
|
1183
|
+
/* Remove it and continue detaching other nodes */
|
1184
|
+
/* above this one, because no other patterns are */
|
1185
|
+
/* dependent upon this node. */
|
1186
|
+
/*===============================================*/
|
1187
|
+
|
1188
|
+
patternPtr = upperLevel;
|
1189
|
+
upperLevel = patternPtr->lastLevel;
|
1190
|
+
|
1191
|
+
if (upperLevel == NULL)
|
1192
|
+
SetObjectNetworkPointer(theEnv,NULL);
|
1193
|
+
else
|
1194
|
+
{
|
1195
|
+
if (upperLevel->selector)
|
1196
|
+
{ RemoveHashedPatternNode(theEnv,upperLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
|
1197
|
+
|
1198
|
+
upperLevel->nextLevel = NULL;
|
1199
|
+
if (upperLevel->alphaNode != NULL)
|
1200
|
+
upperLevel = NULL;
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
RemoveHashedExpression(theEnv,(Expression *) patternPtr->networkTest);
|
1204
|
+
rtn_struct(theEnv,objectPatternNode,patternPtr);
|
1205
|
+
}
|
1206
|
+
else if (upperLevel->leftNode != NULL)
|
1207
|
+
{
|
1208
|
+
/*====================================================*/
|
1209
|
+
/* Pattern node has another pattern node which must */
|
1210
|
+
/* be checked preceding it. Remove the pattern node, */
|
1211
|
+
/* but do not detach any nodes above this one. */
|
1212
|
+
/*====================================================*/
|
1213
|
+
|
1214
|
+
patternPtr = upperLevel;
|
1215
|
+
|
1216
|
+
if ((patternPtr->lastLevel != NULL) &&
|
1217
|
+
(patternPtr->lastLevel->selector))
|
1218
|
+
{ RemoveHashedPatternNode(theEnv,patternPtr->lastLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
|
1219
|
+
|
1220
|
+
upperLevel->leftNode->rightNode = upperLevel->rightNode;
|
1221
|
+
if (upperLevel->rightNode != NULL)
|
1222
|
+
{ upperLevel->rightNode->leftNode = upperLevel->leftNode; }
|
1223
|
+
|
1224
|
+
RemoveHashedExpression(theEnv,(Expression *) patternPtr->networkTest);
|
1225
|
+
rtn_struct(theEnv,objectPatternNode,patternPtr);
|
1226
|
+
upperLevel = NULL;
|
1227
|
+
}
|
1228
|
+
else
|
1229
|
+
{
|
1230
|
+
/*====================================================*/
|
1231
|
+
/* Pattern node has no pattern node preceding it, but */
|
1232
|
+
/* does have one succeeding it. Remove the pattern */
|
1233
|
+
/* node, but do not detach any nodes above this one. */
|
1234
|
+
/*====================================================*/
|
1235
|
+
|
1236
|
+
patternPtr = upperLevel;
|
1237
|
+
upperLevel = upperLevel->lastLevel;
|
1238
|
+
if (upperLevel == NULL)
|
1239
|
+
{ SetObjectNetworkPointer(theEnv,patternPtr->rightNode); }
|
1240
|
+
else
|
1241
|
+
{
|
1242
|
+
if (upperLevel->selector)
|
1243
|
+
{ RemoveHashedPatternNode(theEnv,upperLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
|
1244
|
+
|
1245
|
+
upperLevel->nextLevel = patternPtr->rightNode;
|
1246
|
+
}
|
1247
|
+
patternPtr->rightNode->leftNode = NULL;
|
1248
|
+
|
1249
|
+
RemoveHashedExpression(theEnv,(Expression *) patternPtr->networkTest);
|
1250
|
+
rtn_struct(theEnv,objectPatternNode,patternPtr);
|
1251
|
+
upperLevel = NULL;
|
1252
|
+
}
|
1253
|
+
}
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
/***************************************************
|
1257
|
+
NAME : ClearObjectPatternMatches
|
1258
|
+
DESCRIPTION : Removes a pattern node alpha memory
|
1259
|
+
from the list of partial matches
|
1260
|
+
on all instances (active or
|
1261
|
+
garbage collected)
|
1262
|
+
INPUTS : The pattern node to remove
|
1263
|
+
RETURNS : Nothing useful
|
1264
|
+
SIDE EFFECTS : Pattern alpha memory removed
|
1265
|
+
from all object partial match lists
|
1266
|
+
NOTES : Used when a pattern is removed
|
1267
|
+
***************************************************/
|
1268
|
+
static void ClearObjectPatternMatches(
|
1269
|
+
Environment *theEnv,
|
1270
|
+
OBJECT_ALPHA_NODE *alphaPtr)
|
1271
|
+
{
|
1272
|
+
Instance *ins;
|
1273
|
+
IGARBAGE *igrb;
|
1274
|
+
|
1275
|
+
/* =============================================
|
1276
|
+
Loop through every active and queued instance
|
1277
|
+
============================================= */
|
1278
|
+
ins = InstanceData(theEnv)->InstanceList;
|
1279
|
+
while (ins != NULL)
|
1280
|
+
{
|
1281
|
+
RemoveObjectPartialMatches(theEnv,ins,(struct patternNodeHeader *) alphaPtr);
|
1282
|
+
ins = ins->nxtList;
|
1283
|
+
}
|
1284
|
+
|
1285
|
+
/* ============================
|
1286
|
+
Check for garbaged instances
|
1287
|
+
============================ */
|
1288
|
+
igrb = InstanceData(theEnv)->InstanceGarbageList;
|
1289
|
+
while (igrb != NULL)
|
1290
|
+
{
|
1291
|
+
RemoveObjectPartialMatches(theEnv,igrb->ins,(struct patternNodeHeader *) alphaPtr);
|
1292
|
+
igrb = igrb->nxt;
|
1293
|
+
}
|
1294
|
+
}
|
1295
|
+
|
1296
|
+
/***************************************************
|
1297
|
+
NAME : RemoveObjectPartialMatches
|
1298
|
+
DESCRIPTION : Removes a partial match from a
|
1299
|
+
list of partial matches for
|
1300
|
+
an instance
|
1301
|
+
INPUTS : 1) The instance
|
1302
|
+
2) The pattern node header
|
1303
|
+
corresponding to the match
|
1304
|
+
RETURNS : Nothing useful
|
1305
|
+
SIDE EFFECTS : Match removed
|
1306
|
+
NOTES : None
|
1307
|
+
***************************************************/
|
1308
|
+
static void RemoveObjectPartialMatches(
|
1309
|
+
Environment *theEnv,
|
1310
|
+
Instance *ins,
|
1311
|
+
struct patternNodeHeader *phead)
|
1312
|
+
{
|
1313
|
+
struct patternMatch *match_before, *match_ptr;
|
1314
|
+
|
1315
|
+
match_before = NULL;
|
1316
|
+
match_ptr = (struct patternMatch *) ins->partialMatchList;
|
1317
|
+
|
1318
|
+
/* =======================================
|
1319
|
+
Loop through every match for the object
|
1320
|
+
======================================= */
|
1321
|
+
while (match_ptr != NULL)
|
1322
|
+
{
|
1323
|
+
if (match_ptr->matchingPattern == phead)
|
1324
|
+
{
|
1325
|
+
ins->busy--;
|
1326
|
+
if (match_before == NULL)
|
1327
|
+
{
|
1328
|
+
ins->partialMatchList = (void *) match_ptr->next;
|
1329
|
+
rtn_struct(theEnv,patternMatch,match_ptr);
|
1330
|
+
match_ptr = (struct patternMatch *) ins->partialMatchList;
|
1331
|
+
}
|
1332
|
+
else
|
1333
|
+
{
|
1334
|
+
match_before->next = match_ptr->next;
|
1335
|
+
rtn_struct(theEnv,patternMatch,match_ptr);
|
1336
|
+
match_ptr = match_before->next;
|
1337
|
+
}
|
1338
|
+
}
|
1339
|
+
else
|
1340
|
+
{
|
1341
|
+
match_before = match_ptr;
|
1342
|
+
match_ptr = match_ptr->next;
|
1343
|
+
}
|
1344
|
+
}
|
1345
|
+
}
|
1346
|
+
|
1347
|
+
/******************************************************
|
1348
|
+
NAME : CheckDuplicateSlots
|
1349
|
+
DESCRIPTION : Determines if a restriction has
|
1350
|
+
already been defined in a pattern
|
1351
|
+
INPUTS : The list of already built restrictions
|
1352
|
+
RETURNS : True if a definition already
|
1353
|
+
exists, false otherwise
|
1354
|
+
SIDE EFFECTS : An error message is printed if a
|
1355
|
+
duplicate is found
|
1356
|
+
NOTES : None
|
1357
|
+
******************************************************/
|
1358
|
+
static bool CheckDuplicateSlots(
|
1359
|
+
Environment *theEnv,
|
1360
|
+
struct lhsParseNode *nodeList,
|
1361
|
+
CLIPSLexeme *slotName)
|
1362
|
+
{
|
1363
|
+
while (nodeList != NULL)
|
1364
|
+
{
|
1365
|
+
if (nodeList->slot == slotName)
|
1366
|
+
{
|
1367
|
+
PrintErrorID(theEnv,"OBJRTBLD",4,true);
|
1368
|
+
WriteString(theEnv,STDERR,"Multiple restrictions on attribute '");
|
1369
|
+
WriteString(theEnv,STDERR,slotName->contents);
|
1370
|
+
WriteString(theEnv,STDERR,"' not allowed.\n");
|
1371
|
+
return true;
|
1372
|
+
}
|
1373
|
+
nodeList = nodeList->right;
|
1374
|
+
}
|
1375
|
+
return false;
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
/**********************************************************
|
1379
|
+
NAME : ParseClassRestriction
|
1380
|
+
DESCRIPTION : Parses the single-field constraint
|
1381
|
+
on the class an object pattern
|
1382
|
+
INPUTS : 1) The logical input source
|
1383
|
+
2) A buffer for tokens
|
1384
|
+
RETURNS : The intermediate pattern nodes
|
1385
|
+
representing the class constraint
|
1386
|
+
(NULL on errors)
|
1387
|
+
SIDE EFFECTS : Intermediate pattern nodes allocated
|
1388
|
+
NOTES : None
|
1389
|
+
**********************************************************/
|
1390
|
+
static struct lhsParseNode *ParseClassRestriction(
|
1391
|
+
Environment *theEnv,
|
1392
|
+
const char *readSource,
|
1393
|
+
struct token *theToken)
|
1394
|
+
{
|
1395
|
+
struct lhsParseNode *tmpNode;
|
1396
|
+
CLIPSLexeme *rln;
|
1397
|
+
CONSTRAINT_RECORD *rv;
|
1398
|
+
|
1399
|
+
rv = GetConstraintRecord(theEnv);
|
1400
|
+
rv->anyAllowed = 0;
|
1401
|
+
rv->symbolsAllowed = 1;
|
1402
|
+
rln = theToken->lexemeValue;
|
1403
|
+
SavePPBuffer(theEnv," ");
|
1404
|
+
GetToken(theEnv,readSource,theToken);
|
1405
|
+
tmpNode = RestrictionParse(theEnv,readSource,theToken,false,rln,ISA_ID,rv,0);
|
1406
|
+
if (tmpNode == NULL)
|
1407
|
+
{
|
1408
|
+
RemoveConstraint(theEnv,rv);
|
1409
|
+
return NULL;
|
1410
|
+
}
|
1411
|
+
if ((theToken->tknType != RIGHT_PARENTHESIS_TOKEN) ||
|
1412
|
+
(tmpNode->pnType == MF_WILDCARD_NODE) ||
|
1413
|
+
(tmpNode->pnType == MF_VARIABLE_NODE))
|
1414
|
+
{
|
1415
|
+
PPBackup(theEnv);
|
1416
|
+
if (theToken->tknType != RIGHT_PARENTHESIS_TOKEN)
|
1417
|
+
{
|
1418
|
+
SavePPBuffer(theEnv," ");
|
1419
|
+
SavePPBuffer(theEnv,theToken->printForm);
|
1420
|
+
}
|
1421
|
+
SyntaxErrorMessage(theEnv,"class restriction in object pattern");
|
1422
|
+
ReturnLHSParseNodes(theEnv,tmpNode);
|
1423
|
+
RemoveConstraint(theEnv,rv);
|
1424
|
+
return NULL;
|
1425
|
+
}
|
1426
|
+
tmpNode->derivedConstraints = 1;
|
1427
|
+
return(tmpNode);
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
/**********************************************************
|
1431
|
+
NAME : ParseNameRestriction
|
1432
|
+
DESCRIPTION : Parses the single-field constraint
|
1433
|
+
on the name of an object pattern
|
1434
|
+
INPUTS : 1) The logical input source
|
1435
|
+
2) A buffer for tokens
|
1436
|
+
RETURNS : The intermediate pattern nodes
|
1437
|
+
representing the name constraint
|
1438
|
+
(NULL on errors)
|
1439
|
+
SIDE EFFECTS : Intermediate pattern nodes allocated
|
1440
|
+
NOTES : None
|
1441
|
+
**********************************************************/
|
1442
|
+
static struct lhsParseNode *ParseNameRestriction(
|
1443
|
+
Environment *theEnv,
|
1444
|
+
const char *readSource,
|
1445
|
+
struct token *theToken)
|
1446
|
+
{
|
1447
|
+
struct lhsParseNode *tmpNode;
|
1448
|
+
CLIPSLexeme *rln;
|
1449
|
+
CONSTRAINT_RECORD *rv;
|
1450
|
+
|
1451
|
+
rv = GetConstraintRecord(theEnv);
|
1452
|
+
rv->anyAllowed = 0;
|
1453
|
+
rv->instanceNamesAllowed = 1;
|
1454
|
+
rln = theToken->lexemeValue;
|
1455
|
+
SavePPBuffer(theEnv," ");
|
1456
|
+
GetToken(theEnv,readSource,theToken);
|
1457
|
+
tmpNode = RestrictionParse(theEnv,readSource,theToken,false,rln,NAME_ID,rv,0);
|
1458
|
+
if (tmpNode == NULL)
|
1459
|
+
{
|
1460
|
+
RemoveConstraint(theEnv,rv);
|
1461
|
+
return NULL;
|
1462
|
+
}
|
1463
|
+
if ((theToken->tknType != RIGHT_PARENTHESIS_TOKEN) ||
|
1464
|
+
(tmpNode->pnType == MF_WILDCARD_NODE) ||
|
1465
|
+
(tmpNode->pnType == MF_VARIABLE_NODE))
|
1466
|
+
{
|
1467
|
+
PPBackup(theEnv);
|
1468
|
+
if (theToken->tknType != RIGHT_PARENTHESIS_TOKEN)
|
1469
|
+
{
|
1470
|
+
SavePPBuffer(theEnv," ");
|
1471
|
+
SavePPBuffer(theEnv,theToken->printForm);
|
1472
|
+
}
|
1473
|
+
SyntaxErrorMessage(theEnv,"name restriction in object pattern");
|
1474
|
+
ReturnLHSParseNodes(theEnv,tmpNode);
|
1475
|
+
RemoveConstraint(theEnv,rv);
|
1476
|
+
return NULL;
|
1477
|
+
}
|
1478
|
+
|
1479
|
+
tmpNode->derivedConstraints = 1;
|
1480
|
+
return(tmpNode);
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
/***************************************************
|
1484
|
+
NAME : ParseSlotRestriction
|
1485
|
+
DESCRIPTION : Parses the field constraint(s)
|
1486
|
+
on a slot of an object pattern
|
1487
|
+
INPUTS : 1) The logical input source
|
1488
|
+
2) A buffer for tokens
|
1489
|
+
3) Constraint record holding the
|
1490
|
+
unioned constraints of all the
|
1491
|
+
slots which could match the
|
1492
|
+
slot pattern
|
1493
|
+
4) A flag indicating if any
|
1494
|
+
multifield slots match the name
|
1495
|
+
RETURNS : The intermediate pattern nodes
|
1496
|
+
representing the slot constraint(s)
|
1497
|
+
(NULL on errors)
|
1498
|
+
SIDE EFFECTS : Intermediate pattern nodes
|
1499
|
+
allocated
|
1500
|
+
NOTES : None
|
1501
|
+
***************************************************/
|
1502
|
+
static struct lhsParseNode *ParseSlotRestriction(
|
1503
|
+
Environment *theEnv,
|
1504
|
+
const char *readSource,
|
1505
|
+
struct token *theToken,
|
1506
|
+
CONSTRAINT_RECORD *slotConstraints,
|
1507
|
+
bool multip)
|
1508
|
+
{
|
1509
|
+
struct lhsParseNode *tmpNode;
|
1510
|
+
CLIPSLexeme *slotName;
|
1511
|
+
|
1512
|
+
slotName = theToken->lexemeValue;
|
1513
|
+
SavePPBuffer(theEnv," ");
|
1514
|
+
GetToken(theEnv,readSource,theToken);
|
1515
|
+
tmpNode = RestrictionParse(theEnv,readSource,theToken,multip,slotName,FindSlotNameID(theEnv,slotName),
|
1516
|
+
slotConstraints,1);
|
1517
|
+
if (tmpNode == NULL)
|
1518
|
+
{
|
1519
|
+
RemoveConstraint(theEnv,slotConstraints);
|
1520
|
+
return NULL;
|
1521
|
+
}
|
1522
|
+
if (theToken->tknType != RIGHT_PARENTHESIS_TOKEN)
|
1523
|
+
{
|
1524
|
+
PPBackup(theEnv);
|
1525
|
+
SavePPBuffer(theEnv," ");
|
1526
|
+
SavePPBuffer(theEnv,theToken->printForm);
|
1527
|
+
SyntaxErrorMessage(theEnv,"object slot pattern");
|
1528
|
+
ReturnLHSParseNodes(theEnv,tmpNode);
|
1529
|
+
RemoveConstraint(theEnv,slotConstraints);
|
1530
|
+
return NULL;
|
1531
|
+
}
|
1532
|
+
if ((tmpNode->bottom == NULL) && (tmpNode->multifieldSlot))
|
1533
|
+
{
|
1534
|
+
PPBackup(theEnv);
|
1535
|
+
PPBackup(theEnv);
|
1536
|
+
SavePPBuffer(theEnv,")");
|
1537
|
+
}
|
1538
|
+
tmpNode->derivedConstraints = 1;
|
1539
|
+
return(tmpNode);
|
1540
|
+
}
|
1541
|
+
|
1542
|
+
/********************************************************
|
1543
|
+
NAME : NewClassBitMap
|
1544
|
+
DESCRIPTION : Creates a new bitmap large enough
|
1545
|
+
to hold all ids of classes in the
|
1546
|
+
system and initializes all the bits
|
1547
|
+
to zero or one.
|
1548
|
+
INPUTS : 1) The maximum id that will be set
|
1549
|
+
in the bitmap
|
1550
|
+
2) An integer code indicating if all
|
1551
|
+
the bits are to be set to zero or one
|
1552
|
+
RETURNS : The new bitmap
|
1553
|
+
SIDE EFFECTS : BitMap allocated and initialized
|
1554
|
+
NOTES : None
|
1555
|
+
********************************************************/
|
1556
|
+
static CLASS_BITMAP *NewClassBitMap(
|
1557
|
+
Environment *theEnv,
|
1558
|
+
unsigned short maxid,
|
1559
|
+
bool set)
|
1560
|
+
{
|
1561
|
+
CLASS_BITMAP *bmp;
|
1562
|
+
size_t size;
|
1563
|
+
|
1564
|
+
size = sizeof(CLASS_BITMAP) + (sizeof(char) * (maxid / BITS_PER_BYTE));
|
1565
|
+
bmp = (CLASS_BITMAP *) gm2(theEnv,size);
|
1566
|
+
ClearBitString(bmp,size);
|
1567
|
+
bmp->maxid = (unsigned short) maxid;
|
1568
|
+
InitializeClassBitMap(theEnv,bmp,set);
|
1569
|
+
|
1570
|
+
return bmp;
|
1571
|
+
}
|
1572
|
+
|
1573
|
+
/***********************************************************
|
1574
|
+
NAME : InitializeClassBitMap
|
1575
|
+
DESCRIPTION : Initializes a bitmap to all zeroes or ones.
|
1576
|
+
INPUTS : 1) The bitmap
|
1577
|
+
2) An integer code indicating if all
|
1578
|
+
the bits are to be set to zero or one
|
1579
|
+
RETURNS : Nothing useful
|
1580
|
+
SIDE EFFECTS : The bitmap is initialized
|
1581
|
+
NOTES : None
|
1582
|
+
***********************************************************/
|
1583
|
+
static void InitializeClassBitMap(
|
1584
|
+
Environment *theEnv,
|
1585
|
+
CLASS_BITMAP *bmp,
|
1586
|
+
bool set)
|
1587
|
+
{
|
1588
|
+
unsigned short i, bytes;
|
1589
|
+
Defclass *cls;
|
1590
|
+
Defmodule *currentModule;
|
1591
|
+
|
1592
|
+
bytes = bmp->maxid / BITS_PER_BYTE + 1;
|
1593
|
+
while (bytes > 0)
|
1594
|
+
{
|
1595
|
+
bmp->map[bytes - 1] = (char) 0;
|
1596
|
+
bytes--;
|
1597
|
+
}
|
1598
|
+
|
1599
|
+
if (set)
|
1600
|
+
{
|
1601
|
+
currentModule = GetCurrentModule(theEnv);
|
1602
|
+
for (i = 0 ; i <= bmp->maxid ; i++)
|
1603
|
+
{
|
1604
|
+
cls = DefclassData(theEnv)->ClassIDMap[i];
|
1605
|
+
if ((cls != NULL) ? DefclassInScope(theEnv,cls,currentModule) : false)
|
1606
|
+
{
|
1607
|
+
if (cls->reactive && (cls->abstract == 0))
|
1608
|
+
SetBitMap(bmp->map,i);
|
1609
|
+
}
|
1610
|
+
}
|
1611
|
+
}
|
1612
|
+
}
|
1613
|
+
|
1614
|
+
/********************************************
|
1615
|
+
NAME : DeleteIntermediateClassBitMap
|
1616
|
+
DESCRIPTION : Deallocates a bitmap
|
1617
|
+
INPUTS : The class set
|
1618
|
+
RETURNS : Nothing useful
|
1619
|
+
SIDE EFFECTS : Class set deallocated
|
1620
|
+
NOTES : None
|
1621
|
+
********************************************/
|
1622
|
+
static void DeleteIntermediateClassBitMap(
|
1623
|
+
Environment *theEnv,
|
1624
|
+
const CLASS_BITMAP *bmp)
|
1625
|
+
{
|
1626
|
+
rm(theEnv,(void *) bmp,ClassBitMapSize(bmp));
|
1627
|
+
}
|
1628
|
+
|
1629
|
+
/******************************************************
|
1630
|
+
NAME : CopyClassBitMap
|
1631
|
+
DESCRIPTION : Increments the in use count of a
|
1632
|
+
bitmap and returns the same pointer
|
1633
|
+
INPUTS : The bitmap
|
1634
|
+
RETURNS : The bitmap
|
1635
|
+
SIDE EFFECTS : Increments the in use count
|
1636
|
+
NOTES : Class sets are shared by multiple
|
1637
|
+
copies of an object pattern within an
|
1638
|
+
OR CE. The use count prevents having
|
1639
|
+
to make duplicate copies of the bitmap
|
1640
|
+
******************************************************/
|
1641
|
+
static void *CopyClassBitMap(
|
1642
|
+
Environment *theEnv,
|
1643
|
+
void *gset)
|
1644
|
+
{
|
1645
|
+
#if MAC_XCD
|
1646
|
+
#pragma unused(theEnv)
|
1647
|
+
#endif
|
1648
|
+
|
1649
|
+
if (gset != NULL)
|
1650
|
+
IncrementBitMapCount(gset);
|
1651
|
+
return(gset);
|
1652
|
+
}
|
1653
|
+
|
1654
|
+
/**********************************************************
|
1655
|
+
NAME : DeleteClassBitMap
|
1656
|
+
DESCRIPTION : Deallocates a bitmap,
|
1657
|
+
and decrements the busy flags of the
|
1658
|
+
classes marked in the bitmap
|
1659
|
+
INPUTS : The bitmap
|
1660
|
+
RETURNS : Nothing useful
|
1661
|
+
SIDE EFFECTS : Class set deallocated and classes unmarked
|
1662
|
+
NOTES : None
|
1663
|
+
**********************************************************/
|
1664
|
+
static void DeleteClassBitMap(
|
1665
|
+
Environment *theEnv,
|
1666
|
+
void *gset)
|
1667
|
+
{
|
1668
|
+
if (gset == NULL)
|
1669
|
+
return;
|
1670
|
+
DecrementBitMapReferenceCount(theEnv,(CLIPSBitMap *) gset);
|
1671
|
+
}
|
1672
|
+
|
1673
|
+
/***************************************************
|
1674
|
+
NAME : MarkBitMapClassesBusy
|
1675
|
+
DESCRIPTION : Increments/Decrements busy counts
|
1676
|
+
of all classes marked in a bitmap
|
1677
|
+
INPUTS : 1) The bitmap hash node
|
1678
|
+
2) 1 or -1 (to increment or
|
1679
|
+
decrement class busy counts)
|
1680
|
+
RETURNS : Nothing useful
|
1681
|
+
SIDE EFFECTS : Bitmap class busy counts updated
|
1682
|
+
NOTES : None
|
1683
|
+
***************************************************/
|
1684
|
+
static void MarkBitMapClassesBusy(
|
1685
|
+
Environment *theEnv,
|
1686
|
+
CLIPSBitMap *bmphn,
|
1687
|
+
int offset)
|
1688
|
+
{
|
1689
|
+
const CLASS_BITMAP *bmp;
|
1690
|
+
unsigned short i;
|
1691
|
+
Defclass *cls;
|
1692
|
+
|
1693
|
+
/* ====================================
|
1694
|
+
If a clear is in progress, we do not
|
1695
|
+
have to worry about busy counts
|
1696
|
+
==================================== */
|
1697
|
+
if (ConstructData(theEnv)->ClearInProgress)
|
1698
|
+
return;
|
1699
|
+
bmp = (const CLASS_BITMAP *) bmphn->contents;
|
1700
|
+
for (i = 0 ; i <= bmp->maxid ; i++)
|
1701
|
+
if (TestBitMap(bmp->map,i))
|
1702
|
+
{
|
1703
|
+
cls = DefclassData(theEnv)->ClassIDMap[i];
|
1704
|
+
cls->busy += (unsigned int) offset;
|
1705
|
+
}
|
1706
|
+
}
|
1707
|
+
|
1708
|
+
/****************************************************
|
1709
|
+
NAME : EmptyClassBitMap
|
1710
|
+
DESCRIPTION : Determines if one or more bits
|
1711
|
+
are marked in a bitmap
|
1712
|
+
INPUTS : The bitmap
|
1713
|
+
RETURNS : True if the set has no bits
|
1714
|
+
marked, false otherwise
|
1715
|
+
SIDE EFFECTS : None
|
1716
|
+
NOTES : None
|
1717
|
+
****************************************************/
|
1718
|
+
static bool EmptyClassBitMap(
|
1719
|
+
CLASS_BITMAP *bmp)
|
1720
|
+
{
|
1721
|
+
unsigned short bytes;
|
1722
|
+
|
1723
|
+
bytes = (unsigned short) (bmp->maxid / BITS_PER_BYTE + 1);
|
1724
|
+
while (bytes > 0)
|
1725
|
+
{
|
1726
|
+
if (bmp->map[bytes - 1] != (char) 0)
|
1727
|
+
return false;
|
1728
|
+
bytes--;
|
1729
|
+
}
|
1730
|
+
return true;
|
1731
|
+
}
|
1732
|
+
|
1733
|
+
/***************************************************
|
1734
|
+
NAME : IdenticalClassBitMap
|
1735
|
+
DESCRIPTION : Determines if two bitmaps
|
1736
|
+
are identical
|
1737
|
+
INPUTS : 1) First bitmap
|
1738
|
+
2) Second bitmap
|
1739
|
+
RETURNS : True if bitmaps are the same,
|
1740
|
+
false otherwise
|
1741
|
+
SIDE EFFECTS : None
|
1742
|
+
NOTES : None
|
1743
|
+
***************************************************/
|
1744
|
+
static bool IdenticalClassBitMap(
|
1745
|
+
const CLASS_BITMAP *cs1,
|
1746
|
+
const CLASS_BITMAP *cs2)
|
1747
|
+
{
|
1748
|
+
unsigned short i;
|
1749
|
+
|
1750
|
+
if (cs1->maxid != cs2->maxid)
|
1751
|
+
return false;
|
1752
|
+
for (i = 0 ; i < (cs1->maxid / BITS_PER_BYTE + 1) ; i++)
|
1753
|
+
if (cs1->map[i] != cs2->map[i])
|
1754
|
+
return false;
|
1755
|
+
return true;
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
/*****************************************************************
|
1759
|
+
NAME : ProcessClassRestriction
|
1760
|
+
DESCRIPTION : Examines a class restriction and forms a bitmap
|
1761
|
+
corresponding to the maximal set of classes which
|
1762
|
+
can satisfy a static analysis of the restriction
|
1763
|
+
INPUTS : 1) The bitmap to mark classes in
|
1764
|
+
2) The lhsParseNodes of the restriction
|
1765
|
+
3) A flag indicating if this is the first
|
1766
|
+
non-recursive call or not
|
1767
|
+
RETURNS : True if all OK, false otherwise
|
1768
|
+
SIDE EFFECTS : Class bitmap set and lhsParseNodes corressponding
|
1769
|
+
to constant restrictions are removed
|
1770
|
+
NOTES : None
|
1771
|
+
*****************************************************************/
|
1772
|
+
static bool ProcessClassRestriction(
|
1773
|
+
Environment *theEnv,
|
1774
|
+
CLASS_BITMAP *clsset,
|
1775
|
+
struct lhsParseNode **classRestrictions,
|
1776
|
+
bool recursiveCall)
|
1777
|
+
{
|
1778
|
+
struct lhsParseNode *chk,**oraddr;
|
1779
|
+
CLASS_BITMAP *tmpset1,*tmpset2;
|
1780
|
+
bool constant_restriction = true;
|
1781
|
+
|
1782
|
+
if (*classRestrictions == NULL)
|
1783
|
+
{
|
1784
|
+
if (recursiveCall)
|
1785
|
+
InitializeClassBitMap(theEnv,clsset,true);
|
1786
|
+
return true;
|
1787
|
+
}
|
1788
|
+
|
1789
|
+
/* ===============================================
|
1790
|
+
Determine the corresponding class set and union
|
1791
|
+
it with the current total class set. If an AND
|
1792
|
+
restriction is comprised entirely of symbols,
|
1793
|
+
it can be removed
|
1794
|
+
=============================================== */
|
1795
|
+
tmpset1 = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,1);
|
1796
|
+
tmpset2 = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,0);
|
1797
|
+
for (chk = *classRestrictions ; chk != NULL ; chk = chk->right)
|
1798
|
+
{
|
1799
|
+
if (chk->pnType == SYMBOL_NODE)
|
1800
|
+
{
|
1801
|
+
const char *className = chk->lexemeValue->contents;
|
1802
|
+
|
1803
|
+
chk->value = LookupDefclassByMdlOrScope(theEnv,className);
|
1804
|
+
if (chk->value == NULL)
|
1805
|
+
{
|
1806
|
+
PrintErrorID(theEnv,"OBJRTBLD",5,false);
|
1807
|
+
WriteString(theEnv,STDERR,"Undefined class '");
|
1808
|
+
WriteString(theEnv,STDERR,className);
|
1809
|
+
WriteString(theEnv,STDERR,"' in object pattern.\n");
|
1810
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset1);
|
1811
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset2);
|
1812
|
+
return false;
|
1813
|
+
}
|
1814
|
+
if (chk->negated)
|
1815
|
+
{
|
1816
|
+
InitializeClassBitMap(theEnv,tmpset2,true);
|
1817
|
+
MarkBitMapSubclasses(tmpset2->map,(Defclass *) chk->value,0);
|
1818
|
+
}
|
1819
|
+
else
|
1820
|
+
{
|
1821
|
+
InitializeClassBitMap(theEnv,tmpset2,false);
|
1822
|
+
MarkBitMapSubclasses(tmpset2->map,(Defclass *) chk->value,1);
|
1823
|
+
}
|
1824
|
+
IntersectClassBitMaps(tmpset1,tmpset2);
|
1825
|
+
}
|
1826
|
+
else
|
1827
|
+
constant_restriction = false;
|
1828
|
+
}
|
1829
|
+
if (EmptyClassBitMap(tmpset1))
|
1830
|
+
{
|
1831
|
+
PrintErrorID(theEnv,"OBJRTBLD",2,false);
|
1832
|
+
WriteString(theEnv,STDERR,"No objects of existing classes can satisfy ");
|
1833
|
+
WriteString(theEnv,STDERR,"'is-a' restriction in object pattern.\n");
|
1834
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset1);
|
1835
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset2);
|
1836
|
+
return false;
|
1837
|
+
}
|
1838
|
+
if (constant_restriction)
|
1839
|
+
{
|
1840
|
+
chk = *classRestrictions;
|
1841
|
+
*classRestrictions = chk->bottom;
|
1842
|
+
chk->bottom = NULL;
|
1843
|
+
ReturnLHSParseNodes(theEnv,chk);
|
1844
|
+
oraddr = classRestrictions;
|
1845
|
+
}
|
1846
|
+
else
|
1847
|
+
oraddr = &(*classRestrictions)->bottom;
|
1848
|
+
UnionClassBitMaps(clsset,tmpset1);
|
1849
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset1);
|
1850
|
+
DeleteIntermediateClassBitMap(theEnv,tmpset2);
|
1851
|
+
|
1852
|
+
/* =====================================
|
1853
|
+
Process the next OR class restriction
|
1854
|
+
===================================== */
|
1855
|
+
return(ProcessClassRestriction(theEnv,clsset,oraddr,false));
|
1856
|
+
}
|
1857
|
+
|
1858
|
+
/****************************************************************
|
1859
|
+
NAME : ProcessSlotRestriction
|
1860
|
+
DESCRIPTION : Determines which slots could match the slot
|
1861
|
+
pattern and determines the union of all
|
1862
|
+
constraints for the pattern
|
1863
|
+
INPUTS : 1) The class set
|
1864
|
+
2) The slot name
|
1865
|
+
3) A buffer to hold a flag indicating if
|
1866
|
+
any multifield slots are found w/ this name
|
1867
|
+
RETURNS : A union of the constraints on all the slots
|
1868
|
+
which could match the slots (NULL if no
|
1869
|
+
slots found)
|
1870
|
+
SIDE EFFECTS : The class bitmap set is marked/cleared
|
1871
|
+
NOTES : None
|
1872
|
+
****************************************************************/
|
1873
|
+
static CONSTRAINT_RECORD *ProcessSlotRestriction(
|
1874
|
+
Environment *theEnv,
|
1875
|
+
CLASS_BITMAP *clsset,
|
1876
|
+
CLIPSLexeme *slotName,
|
1877
|
+
bool *multip)
|
1878
|
+
{
|
1879
|
+
Defclass *cls;
|
1880
|
+
int si;
|
1881
|
+
CONSTRAINT_RECORD *totalConstraints = NULL,*tmpConstraints;
|
1882
|
+
unsigned i;
|
1883
|
+
|
1884
|
+
*multip = false;
|
1885
|
+
for (i = 0 ; i < CLASS_TABLE_HASH_SIZE ; i++)
|
1886
|
+
for (cls = DefclassData(theEnv)->ClassTable[i] ; cls != NULL ; cls = cls->nxtHash)
|
1887
|
+
{
|
1888
|
+
if (TestBitMap(clsset->map,cls->id))
|
1889
|
+
{
|
1890
|
+
si = FindInstanceTemplateSlot(theEnv,cls,slotName);
|
1891
|
+
if ((si != -1) ? cls->instanceTemplate[si]->reactive : false)
|
1892
|
+
{
|
1893
|
+
if (cls->instanceTemplate[si]->multiple)
|
1894
|
+
*multip = true;
|
1895
|
+
tmpConstraints =
|
1896
|
+
UnionConstraints(theEnv,cls->instanceTemplate[si]->constraint,totalConstraints);
|
1897
|
+
RemoveConstraint(theEnv,totalConstraints);
|
1898
|
+
totalConstraints = tmpConstraints;
|
1899
|
+
}
|
1900
|
+
else
|
1901
|
+
ClearBitMap(clsset->map,cls->id);
|
1902
|
+
}
|
1903
|
+
}
|
1904
|
+
return(totalConstraints);
|
1905
|
+
}
|
1906
|
+
|
1907
|
+
/****************************************************
|
1908
|
+
NAME : IntersectClassBitMaps
|
1909
|
+
DESCRIPTION : Bitwise-ands two bitmaps and stores
|
1910
|
+
the result in the first
|
1911
|
+
INPUTS : The two bitmaps
|
1912
|
+
RETURNS : Nothing useful
|
1913
|
+
SIDE EFFECTS : ClassBitMaps anded
|
1914
|
+
NOTES : Assumes the first bitmap is at least
|
1915
|
+
as large as the second
|
1916
|
+
****************************************************/
|
1917
|
+
static void IntersectClassBitMaps(
|
1918
|
+
CLASS_BITMAP *cs1,
|
1919
|
+
CLASS_BITMAP *cs2)
|
1920
|
+
{
|
1921
|
+
unsigned short bytes;
|
1922
|
+
|
1923
|
+
bytes = (unsigned short) (cs2->maxid / BITS_PER_BYTE + 1);
|
1924
|
+
while (bytes > 0)
|
1925
|
+
{
|
1926
|
+
cs1->map[bytes - 1] &= cs2->map[bytes - 1];
|
1927
|
+
bytes--;
|
1928
|
+
}
|
1929
|
+
}
|
1930
|
+
|
1931
|
+
/****************************************************
|
1932
|
+
NAME : UnionClassBitMaps
|
1933
|
+
DESCRIPTION : Bitwise-ors two bitmaps and stores
|
1934
|
+
the result in the first
|
1935
|
+
INPUTS : The two bitmaps
|
1936
|
+
RETURNS : Nothing useful
|
1937
|
+
SIDE EFFECTS : ClassBitMaps ored
|
1938
|
+
NOTES : Assumes the first bitmap is at least
|
1939
|
+
as large as the second
|
1940
|
+
****************************************************/
|
1941
|
+
static void UnionClassBitMaps(
|
1942
|
+
CLASS_BITMAP *cs1,
|
1943
|
+
CLASS_BITMAP *cs2)
|
1944
|
+
{
|
1945
|
+
unsigned short bytes;
|
1946
|
+
|
1947
|
+
bytes = (unsigned short) (cs2->maxid / BITS_PER_BYTE + 1);
|
1948
|
+
while (bytes > 0)
|
1949
|
+
{
|
1950
|
+
cs1->map[bytes - 1] |= cs2->map[bytes - 1];
|
1951
|
+
bytes--;
|
1952
|
+
}
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
/*****************************************************
|
1956
|
+
NAME : PackClassBitMap
|
1957
|
+
DESCRIPTION : This routine packs a bitmap
|
1958
|
+
bitmap such that at least one of
|
1959
|
+
the bits in the rightmost byte is
|
1960
|
+
set (i.e. the bitmap takes up
|
1961
|
+
the smallest space possible).
|
1962
|
+
INPUTS : The bitmap
|
1963
|
+
RETURNS : The new (packed) bitmap
|
1964
|
+
SIDE EFFECTS : The oldset is deallocated
|
1965
|
+
NOTES : None
|
1966
|
+
*****************************************************/
|
1967
|
+
static CLASS_BITMAP *PackClassBitMap(
|
1968
|
+
Environment *theEnv,
|
1969
|
+
CLASS_BITMAP *oldset)
|
1970
|
+
{
|
1971
|
+
unsigned short newmaxid;
|
1972
|
+
CLASS_BITMAP *newset;
|
1973
|
+
|
1974
|
+
for (newmaxid = oldset->maxid ; newmaxid > 0 ; newmaxid--)
|
1975
|
+
if (TestBitMap(oldset->map,newmaxid))
|
1976
|
+
break;
|
1977
|
+
if (newmaxid != oldset->maxid)
|
1978
|
+
{
|
1979
|
+
newset = NewClassBitMap(theEnv,newmaxid,0);
|
1980
|
+
GenCopyMemory(char,newmaxid / BITS_PER_BYTE + 1,newset->map,oldset->map);
|
1981
|
+
DeleteIntermediateClassBitMap(theEnv,oldset);
|
1982
|
+
}
|
1983
|
+
else
|
1984
|
+
newset = oldset;
|
1985
|
+
return(newset);
|
1986
|
+
}
|
1987
|
+
|
1988
|
+
/*****************************************************************
|
1989
|
+
NAME : FilterObjectPattern
|
1990
|
+
DESCRIPTION : Appends an extra node to hold the bitmap,
|
1991
|
+
and finds is-a and name nodes
|
1992
|
+
INPUTS : 1) The object pattern parser address
|
1993
|
+
to give to a default is-a slot
|
1994
|
+
2) The unfiltered slot list
|
1995
|
+
3) A buffer to hold the address of
|
1996
|
+
the class bitmap restriction node
|
1997
|
+
4) A buffer to hold the address of
|
1998
|
+
the is-a restriction node
|
1999
|
+
4) A buffer to hold the address of
|
2000
|
+
the name restriction node
|
2001
|
+
RETURNS : The filtered slot list
|
2002
|
+
SIDE EFFECTS : clsset is attached to extra slot pattern
|
2003
|
+
Pointers to the is-a and name slots are also
|
2004
|
+
stored (if they exist) for easy reference
|
2005
|
+
NOTES : None
|
2006
|
+
*****************************************************************/
|
2007
|
+
static struct lhsParseNode *FilterObjectPattern(
|
2008
|
+
Environment *theEnv,
|
2009
|
+
struct patternParser *selfPatternType,
|
2010
|
+
struct lhsParseNode *unfilteredSlots,
|
2011
|
+
struct lhsParseNode **bitmap_slot,
|
2012
|
+
struct lhsParseNode **isa_slot,
|
2013
|
+
struct lhsParseNode **name_slot)
|
2014
|
+
{
|
2015
|
+
struct lhsParseNode *prv,*cur;
|
2016
|
+
|
2017
|
+
*isa_slot = NULL;
|
2018
|
+
*name_slot = NULL;
|
2019
|
+
|
2020
|
+
/* ============================================
|
2021
|
+
Create a dummy node to attach to the end
|
2022
|
+
of the pattern which holds the class bitmap.
|
2023
|
+
============================================ */
|
2024
|
+
*bitmap_slot = GetLHSParseNode(theEnv);
|
2025
|
+
(*bitmap_slot)->pnType = SF_WILDCARD_NODE;
|
2026
|
+
(*bitmap_slot)->slot = DefclassData(theEnv)->ISA_SYMBOL;
|
2027
|
+
(*bitmap_slot)->slotNumber = ISA_ID;
|
2028
|
+
(*bitmap_slot)->index = 1;
|
2029
|
+
(*bitmap_slot)->patternType = selfPatternType;
|
2030
|
+
(*bitmap_slot)->userData = unfilteredSlots->userData;
|
2031
|
+
unfilteredSlots->userData = NULL;
|
2032
|
+
|
2033
|
+
/* ========================
|
2034
|
+
Find is-a and name nodes
|
2035
|
+
======================== */
|
2036
|
+
prv = NULL;
|
2037
|
+
cur = unfilteredSlots;
|
2038
|
+
while (cur != NULL)
|
2039
|
+
{
|
2040
|
+
if (cur->slot == DefclassData(theEnv)->ISA_SYMBOL)
|
2041
|
+
*isa_slot = cur;
|
2042
|
+
else if (cur->slot == DefclassData(theEnv)->NAME_SYMBOL)
|
2043
|
+
*name_slot = cur;
|
2044
|
+
prv = cur;
|
2045
|
+
cur = cur->right;
|
2046
|
+
}
|
2047
|
+
|
2048
|
+
/* ================================
|
2049
|
+
Add the class bitmap conditional
|
2050
|
+
element to end of pattern
|
2051
|
+
================================ */
|
2052
|
+
if (prv == NULL)
|
2053
|
+
unfilteredSlots = *bitmap_slot;
|
2054
|
+
else
|
2055
|
+
prv->right = *bitmap_slot;
|
2056
|
+
return(unfilteredSlots);
|
2057
|
+
}
|
2058
|
+
|
2059
|
+
/***************************************************
|
2060
|
+
NAME : FormSlotBitMap
|
2061
|
+
DESCRIPTION : Examines an object pattern and
|
2062
|
+
forms a minimal bitmap marking
|
2063
|
+
the ids of the slots used in
|
2064
|
+
the pattern
|
2065
|
+
INPUTS : The intermediate parsed pattern
|
2066
|
+
RETURNS : The new slot bitmap (can be NULL)
|
2067
|
+
SIDE EFFECTS : Bitmap created and added to hash
|
2068
|
+
table - corresponding bits set
|
2069
|
+
for ids of slots used in pattern
|
2070
|
+
NOTES : None
|
2071
|
+
***************************************************/
|
2072
|
+
static CLIPSBitMap *FormSlotBitMap(
|
2073
|
+
Environment *theEnv,
|
2074
|
+
struct lhsParseNode *thePattern)
|
2075
|
+
{
|
2076
|
+
struct lhsParseNode *node;
|
2077
|
+
unsigned short maxSlotID = USHRT_MAX;
|
2078
|
+
unsigned size;
|
2079
|
+
SLOT_BITMAP *bmp;
|
2080
|
+
CLIPSBitMap *hshBmp;
|
2081
|
+
|
2082
|
+
/*==========================================*/
|
2083
|
+
/* Find the largest slot id in the pattern. */
|
2084
|
+
/*==========================================*/
|
2085
|
+
|
2086
|
+
for (node = thePattern ; node != NULL ; node = node->right)
|
2087
|
+
{
|
2088
|
+
if (((node->slotNumber > maxSlotID) ||
|
2089
|
+
(maxSlotID == USHRT_MAX)) &&
|
2090
|
+
(node->slotNumber != UNSPECIFIED_SLOT))
|
2091
|
+
{ maxSlotID = node->slotNumber; }
|
2092
|
+
}
|
2093
|
+
|
2094
|
+
/*==================================================*/
|
2095
|
+
/* If the pattern contains no slot tests or only */
|
2096
|
+
/* tests on the class or name (which do not change) */
|
2097
|
+
/* do not store a slot bitmap. */
|
2098
|
+
/*==================================================*/
|
2099
|
+
|
2100
|
+
if ((maxSlotID == ISA_ID) ||
|
2101
|
+
(maxSlotID == NAME_ID) ||
|
2102
|
+
(maxSlotID == USHRT_MAX))
|
2103
|
+
{ return NULL; }
|
2104
|
+
|
2105
|
+
/*======================================*/
|
2106
|
+
/* Initialize the bitmap to all zeroes. */
|
2107
|
+
/*======================================*/
|
2108
|
+
|
2109
|
+
size = (sizeof(SLOT_BITMAP) + (sizeof(char) * (maxSlotID / BITS_PER_BYTE)));
|
2110
|
+
bmp = (SLOT_BITMAP *) gm2(theEnv,size);
|
2111
|
+
ClearBitString(bmp,size);
|
2112
|
+
bmp->maxid = (unsigned short) maxSlotID;
|
2113
|
+
|
2114
|
+
/*===============================================*/
|
2115
|
+
/* Add (retrieve) a bitmap to (from) the bitmap */
|
2116
|
+
/* hash table which has a corresponding bit set */
|
2117
|
+
/* for the id of every slot used in the pattern. */
|
2118
|
+
/*===============================================*/
|
2119
|
+
|
2120
|
+
for (node = thePattern ; node != NULL ; node = node->right)
|
2121
|
+
{ SetBitMap(bmp->map,node->slotNumber); }
|
2122
|
+
|
2123
|
+
hshBmp = (CLIPSBitMap *) AddBitMap(theEnv,bmp,SlotBitMapSize(bmp));
|
2124
|
+
rm(theEnv,bmp,size);
|
2125
|
+
|
2126
|
+
return hshBmp;
|
2127
|
+
}
|
2128
|
+
|
2129
|
+
/****************************************************
|
2130
|
+
NAME : RemoveSlotExistenceTests
|
2131
|
+
DESCRIPTION : Removes slot existence test since
|
2132
|
+
these are accounted for by class
|
2133
|
+
bitmap or name slot.
|
2134
|
+
INPUTS : 1) The intermediate pattern nodes
|
2135
|
+
2) A buffer to hold the class bitmap
|
2136
|
+
RETURNS : The filtered list
|
2137
|
+
SIDE EFFECTS : Slot existence tests removed
|
2138
|
+
NOTES : None
|
2139
|
+
****************************************************/
|
2140
|
+
static struct lhsParseNode *RemoveSlotExistenceTests(
|
2141
|
+
Environment *theEnv,
|
2142
|
+
struct lhsParseNode *thePattern,
|
2143
|
+
CLIPSBitMap **bmp)
|
2144
|
+
{
|
2145
|
+
struct lhsParseNode *tempPattern = thePattern;
|
2146
|
+
struct lhsParseNode *lastPattern = NULL, *head = thePattern;
|
2147
|
+
|
2148
|
+
while (tempPattern != NULL)
|
2149
|
+
{
|
2150
|
+
/* ==========================================
|
2151
|
+
Remember the class bitmap for this pattern
|
2152
|
+
========================================== */
|
2153
|
+
if (tempPattern->userData != NULL)
|
2154
|
+
{
|
2155
|
+
*bmp = (CLIPSBitMap *) tempPattern->userData;
|
2156
|
+
lastPattern = tempPattern;
|
2157
|
+
tempPattern = tempPattern->right;
|
2158
|
+
}
|
2159
|
+
|
2160
|
+
/* ===========================================================
|
2161
|
+
A single field slot that has no pattern network expression
|
2162
|
+
associated with it can be removed (i.e. any value contained
|
2163
|
+
in this slot will satisfy the pattern being matched).
|
2164
|
+
=========================================================== */
|
2165
|
+
else if (((tempPattern->pnType == SF_WILDCARD_NODE) ||
|
2166
|
+
(tempPattern->pnType == SF_VARIABLE_NODE)) &&
|
2167
|
+
(tempPattern->networkTest == NULL))
|
2168
|
+
{
|
2169
|
+
if (lastPattern != NULL) lastPattern->right = tempPattern->right;
|
2170
|
+
else head = tempPattern->right;
|
2171
|
+
|
2172
|
+
tempPattern->right = NULL;
|
2173
|
+
ReturnLHSParseNodes(theEnv,tempPattern);
|
2174
|
+
|
2175
|
+
if (lastPattern != NULL) tempPattern = lastPattern->right;
|
2176
|
+
else tempPattern = head;
|
2177
|
+
}
|
2178
|
+
|
2179
|
+
/* =====================================================
|
2180
|
+
A multifield variable or wildcard within a multifield
|
2181
|
+
slot can be removed if there are no other multifield
|
2182
|
+
variables or wildcards contained in the same slot
|
2183
|
+
(and the multifield has no expressions which must be
|
2184
|
+
evaluated in the fact pattern network).
|
2185
|
+
===================================================== */
|
2186
|
+
else if (((tempPattern->pnType == MF_WILDCARD_NODE) || (tempPattern->pnType == MF_VARIABLE_NODE)) &&
|
2187
|
+
(tempPattern->multifieldSlot == false) &&
|
2188
|
+
(tempPattern->networkTest == NULL) &&
|
2189
|
+
(tempPattern->multiFieldsBefore == 0) &&
|
2190
|
+
(tempPattern->multiFieldsAfter == 0))
|
2191
|
+
{
|
2192
|
+
if (lastPattern != NULL) lastPattern->right = tempPattern->right;
|
2193
|
+
else head = tempPattern->right;
|
2194
|
+
|
2195
|
+
tempPattern->right = NULL;
|
2196
|
+
ReturnLHSParseNodes(theEnv,tempPattern);
|
2197
|
+
|
2198
|
+
if (lastPattern != NULL) tempPattern = lastPattern->right;
|
2199
|
+
else tempPattern = head;
|
2200
|
+
}
|
2201
|
+
|
2202
|
+
/* ================================================================
|
2203
|
+
A multifield wildcard or variable contained in a multifield slot
|
2204
|
+
that contains no other multifield wildcards or variables, but
|
2205
|
+
does have an expression that must be evaluated, can be changed
|
2206
|
+
to a single field pattern node with the same expression.
|
2207
|
+
================================================================ */
|
2208
|
+
else if (((tempPattern->pnType == MF_WILDCARD_NODE) || (tempPattern->pnType == MF_VARIABLE_NODE)) &&
|
2209
|
+
(tempPattern->multifieldSlot == false) &&
|
2210
|
+
(tempPattern->networkTest != NULL) &&
|
2211
|
+
(tempPattern->multiFieldsBefore == 0) &&
|
2212
|
+
(tempPattern->multiFieldsAfter == 0))
|
2213
|
+
{
|
2214
|
+
tempPattern->pnType = SF_WILDCARD_NODE;
|
2215
|
+
lastPattern = tempPattern;
|
2216
|
+
tempPattern = tempPattern->right;
|
2217
|
+
}
|
2218
|
+
|
2219
|
+
/* =======================================================
|
2220
|
+
If we're dealing with a multifield slot with no slot
|
2221
|
+
restrictions, then treat the multfield slot as a single
|
2222
|
+
field slot, but attach a test which verifies that the
|
2223
|
+
slot contains a zero length multifield value.
|
2224
|
+
======================================================= */
|
2225
|
+
else if ((tempPattern->pnType == MF_WILDCARD_NODE) &&
|
2226
|
+
(tempPattern->multifieldSlot == true) &&
|
2227
|
+
(tempPattern->bottom == NULL))
|
2228
|
+
{
|
2229
|
+
tempPattern->pnType = SF_WILDCARD_NODE;
|
2230
|
+
GenObjectZeroLengthTest(theEnv,tempPattern);
|
2231
|
+
tempPattern->multifieldSlot = false;
|
2232
|
+
lastPattern = tempPattern;
|
2233
|
+
tempPattern = tempPattern->right;
|
2234
|
+
}
|
2235
|
+
|
2236
|
+
/* ======================================================
|
2237
|
+
Recursively call RemoveSlotExistenceTests for the slot
|
2238
|
+
restrictions contained within a multifield slot.
|
2239
|
+
====================================================== */
|
2240
|
+
else if ((tempPattern->pnType == MF_WILDCARD_NODE) &&
|
2241
|
+
(tempPattern->multifieldSlot == true))
|
2242
|
+
{
|
2243
|
+
/* =====================================================
|
2244
|
+
Add an expression to the first pattern restriction in
|
2245
|
+
the multifield slot that determines whether or not
|
2246
|
+
the fact's slot value contains the minimum number of
|
2247
|
+
required fields to satisfy the pattern restrictions
|
2248
|
+
for this slot. The length check is place before any
|
2249
|
+
other tests, so that preceeding checks do not have to
|
2250
|
+
determine if there are enough fields in the slot to
|
2251
|
+
safely retrieve a value.
|
2252
|
+
===================================================== */
|
2253
|
+
GenObjectLengthTest(theEnv,tempPattern->bottom);
|
2254
|
+
|
2255
|
+
/* =======================================================
|
2256
|
+
Remove any unneeded pattern restrictions from the slot.
|
2257
|
+
======================================================= */
|
2258
|
+
tempPattern->bottom = RemoveSlotExistenceTests(theEnv,tempPattern->bottom,bmp);
|
2259
|
+
|
2260
|
+
/* =========================================================
|
2261
|
+
If the slot no longer contains any restrictions, then the
|
2262
|
+
multifield slot can be completely removed. In any case,
|
2263
|
+
move on to the next slot to be examined for removal.
|
2264
|
+
========================================================= */
|
2265
|
+
if (tempPattern->bottom == NULL)
|
2266
|
+
{
|
2267
|
+
if (lastPattern != NULL) lastPattern->right = tempPattern->right;
|
2268
|
+
else head = tempPattern->right;
|
2269
|
+
|
2270
|
+
tempPattern->right = NULL;
|
2271
|
+
ReturnLHSParseNodes(theEnv,tempPattern);
|
2272
|
+
|
2273
|
+
if (lastPattern != NULL) tempPattern = lastPattern->right;
|
2274
|
+
else tempPattern = head;
|
2275
|
+
}
|
2276
|
+
else
|
2277
|
+
{
|
2278
|
+
lastPattern = tempPattern;
|
2279
|
+
tempPattern = tempPattern->right;
|
2280
|
+
}
|
2281
|
+
}
|
2282
|
+
|
2283
|
+
/* =====================================================
|
2284
|
+
If none of the other tests for removing slots or slot
|
2285
|
+
restrictions apply, then move on to the next slot or
|
2286
|
+
slot restriction to be tested.
|
2287
|
+
===================================================== */
|
2288
|
+
else
|
2289
|
+
{
|
2290
|
+
lastPattern = tempPattern;
|
2291
|
+
tempPattern = tempPattern->right;
|
2292
|
+
}
|
2293
|
+
}
|
2294
|
+
|
2295
|
+
/* ====================================
|
2296
|
+
Return the pattern with unused slots
|
2297
|
+
and slot restrictions removed.
|
2298
|
+
==================================== */
|
2299
|
+
return(head);
|
2300
|
+
}
|
2301
|
+
|
2302
|
+
#endif
|
2303
|
+
|
2304
|
+
/**************************************************************
|
2305
|
+
NAME : ObjectMatchDelayParse
|
2306
|
+
DESCRIPTION : Parses the object-pattern-match-delay function
|
2307
|
+
INPUTS : 1) The function call expression
|
2308
|
+
2) The logical name of the input source
|
2309
|
+
RETURNS : The top expression with the other
|
2310
|
+
action expressions attached
|
2311
|
+
SIDE EFFECTS : Parses the function call and attaches
|
2312
|
+
the appropriate arguments to the
|
2313
|
+
top node
|
2314
|
+
NOTES : None
|
2315
|
+
**************************************************************/
|
2316
|
+
static Expression *ObjectMatchDelayParse(
|
2317
|
+
Environment *theEnv,
|
2318
|
+
struct expr *top,
|
2319
|
+
const char *infile)
|
2320
|
+
{
|
2321
|
+
struct token tkn;
|
2322
|
+
|
2323
|
+
IncrementIndentDepth(theEnv,3);
|
2324
|
+
PPCRAndIndent(theEnv);
|
2325
|
+
top->argList = GroupActions(theEnv,infile,&tkn,true,NULL,false);
|
2326
|
+
PPBackup(theEnv);
|
2327
|
+
PPBackup(theEnv);
|
2328
|
+
SavePPBuffer(theEnv,tkn.printForm);
|
2329
|
+
DecrementIndentDepth(theEnv,3);
|
2330
|
+
if (top->argList == NULL)
|
2331
|
+
{
|
2332
|
+
ReturnExpression(theEnv,top);
|
2333
|
+
return NULL;
|
2334
|
+
}
|
2335
|
+
return(top);
|
2336
|
+
}
|
2337
|
+
|
2338
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
2339
|
+
|
2340
|
+
/***************************************************
|
2341
|
+
NAME : MarkObjectPtnIncrementalReset
|
2342
|
+
DESCRIPTION : Marks/unmarks an object pattern for
|
2343
|
+
incremental reset
|
2344
|
+
INPUTS : 1) The object pattern alpha node
|
2345
|
+
2) The value to which to set the
|
2346
|
+
incremental reset flag
|
2347
|
+
RETURNS : Nothing useful
|
2348
|
+
SIDE EFFECTS : The pattern node is set/unset
|
2349
|
+
NOTES : The pattern node can only be
|
2350
|
+
set if it is a new node and
|
2351
|
+
thus marked for initialization
|
2352
|
+
by PlaceObjectPattern
|
2353
|
+
***************************************************/
|
2354
|
+
static void MarkObjectPtnIncrementalReset(
|
2355
|
+
Environment *theEnv,
|
2356
|
+
struct patternNodeHeader *thePattern,
|
2357
|
+
bool value)
|
2358
|
+
{
|
2359
|
+
#if MAC_XCD
|
2360
|
+
#pragma unused(theEnv)
|
2361
|
+
#endif
|
2362
|
+
|
2363
|
+
if (thePattern->initialize == false)
|
2364
|
+
return;
|
2365
|
+
thePattern->initialize = value;
|
2366
|
+
}
|
2367
|
+
|
2368
|
+
/***********************************************************
|
2369
|
+
NAME : ObjectIncrementalReset
|
2370
|
+
DESCRIPTION : Performs an assert for all instances in the
|
2371
|
+
system. All new patterns in the pattern
|
2372
|
+
network from the new rule have been marked
|
2373
|
+
as needing processing. Old patterns will
|
2374
|
+
be ignored.
|
2375
|
+
INPUTS : None
|
2376
|
+
RETURNS : Nothing useful
|
2377
|
+
SIDE EFFECTS : All objects driven through new patterns
|
2378
|
+
NOTES : None
|
2379
|
+
***********************************************************/
|
2380
|
+
static void ObjectIncrementalReset(
|
2381
|
+
Environment *theEnv)
|
2382
|
+
{
|
2383
|
+
Instance *ins;
|
2384
|
+
|
2385
|
+
for (ins = InstanceData(theEnv)->InstanceList ; ins != NULL ; ins = ins->nxtList)
|
2386
|
+
ObjectNetworkAction(theEnv,OBJECT_ASSERT,ins,-1);
|
2387
|
+
}
|
2388
|
+
|
2389
|
+
#endif
|
2390
|
+
|
2391
|
+
#endif
|
2392
|
+
|
2393
|
+
|