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,1073 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.41 12/04/22 */
|
5
|
+
/* */
|
6
|
+
/* RULE PARSING MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: Parses a defrule construct. */
|
11
|
+
/* */
|
12
|
+
/* Principal Programmer(s): */
|
13
|
+
/* Gary D. Riley */
|
14
|
+
/* */
|
15
|
+
/* Contributing Programmer(s): */
|
16
|
+
/* */
|
17
|
+
/* Revision History: */
|
18
|
+
/* */
|
19
|
+
/* 6.24: Removed DYNAMIC_SALIENCE, INCREMENTAL_RESET, */
|
20
|
+
/* and LOGICAL_DEPENDENCIES compilation flags. */
|
21
|
+
/* */
|
22
|
+
/* 6.30: Removed conditional code for unsupported */
|
23
|
+
/* compilers/operating systems (IBM_MCW and */
|
24
|
+
/* MAC_MCW). */
|
25
|
+
/* */
|
26
|
+
/* Changed integer type/precision. */
|
27
|
+
/* */
|
28
|
+
/* GetConstructNameAndComment API change. */
|
29
|
+
/* */
|
30
|
+
/* Added support for hashed memories. */
|
31
|
+
/* */
|
32
|
+
/* Added const qualifiers to remove C++ */
|
33
|
+
/* deprecation warnings. */
|
34
|
+
/* */
|
35
|
+
/* Changed find construct functionality so that */
|
36
|
+
/* imported modules are search when locating a */
|
37
|
+
/* named construct. */
|
38
|
+
/* */
|
39
|
+
/* 6.31: DR#882 Logical retraction not working if */
|
40
|
+
/* logical CE starts with test CE. */
|
41
|
+
/* */
|
42
|
+
/* 6.40: Pragma once and other inclusion changes. */
|
43
|
+
/* */
|
44
|
+
/* Added support for booleans with <stdbool.h>. */
|
45
|
+
/* */
|
46
|
+
/* Removed use of void pointers for specific */
|
47
|
+
/* data structures. */
|
48
|
+
/* */
|
49
|
+
/* 6.41: Used gensnprintf in place of gensprintf and. */
|
50
|
+
/* sprintf. */
|
51
|
+
/* */
|
52
|
+
/*************************************************************/
|
53
|
+
|
54
|
+
#include "setup.h"
|
55
|
+
|
56
|
+
#if DEFRULE_CONSTRUCT
|
57
|
+
|
58
|
+
#include <stdio.h>
|
59
|
+
#include <string.h>
|
60
|
+
|
61
|
+
#include "analysis.h"
|
62
|
+
#include "constant.h"
|
63
|
+
#include "constrct.h"
|
64
|
+
#include "cstrcpsr.h"
|
65
|
+
#include "cstrnchk.h"
|
66
|
+
#include "cstrnops.h"
|
67
|
+
#include "engine.h"
|
68
|
+
#include "envrnmnt.h"
|
69
|
+
#include "exprnpsr.h"
|
70
|
+
#include "incrrset.h"
|
71
|
+
#include "memalloc.h"
|
72
|
+
#include "modulutl.h"
|
73
|
+
#include "pattern.h"
|
74
|
+
#include "prccode.h"
|
75
|
+
#include "prcdrpsr.h"
|
76
|
+
#include "pprint.h"
|
77
|
+
#include "prntutil.h"
|
78
|
+
#include "router.h"
|
79
|
+
#include "rulebld.h"
|
80
|
+
#include "rulebsc.h"
|
81
|
+
#include "rulecstr.h"
|
82
|
+
#include "ruledef.h"
|
83
|
+
#include "ruledlt.h"
|
84
|
+
#include "rulelhs.h"
|
85
|
+
#include "scanner.h"
|
86
|
+
#include "symbol.h"
|
87
|
+
#include "watch.h"
|
88
|
+
|
89
|
+
#include "lgcldpnd.h"
|
90
|
+
|
91
|
+
#if DEFTEMPLATE_CONSTRUCT
|
92
|
+
#include "tmpltfun.h"
|
93
|
+
#endif
|
94
|
+
|
95
|
+
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
|
96
|
+
#include "bload.h"
|
97
|
+
#endif
|
98
|
+
|
99
|
+
#include "rulepsr.h"
|
100
|
+
|
101
|
+
/***************************************/
|
102
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
103
|
+
/***************************************/
|
104
|
+
|
105
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
106
|
+
static struct expr *ParseRuleRHS(Environment *,const char *);
|
107
|
+
static int ReplaceRHSVariable(Environment *,struct expr *,void *);
|
108
|
+
static Defrule *ProcessRuleLHS(Environment *,struct lhsParseNode *,struct expr *,CLIPSLexeme *,bool *);
|
109
|
+
static Defrule *CreateNewDisjunct(Environment *,CLIPSLexeme *,unsigned short,struct expr *,
|
110
|
+
unsigned int,unsigned,struct joinNode *);
|
111
|
+
static unsigned short RuleComplexity(Environment *,struct lhsParseNode *);
|
112
|
+
static unsigned short ExpressionComplexity(Environment *,struct expr *);
|
113
|
+
static int LogicalAnalysis(Environment *,struct lhsParseNode *);
|
114
|
+
static void AddToDefruleList(Defrule *);
|
115
|
+
#endif
|
116
|
+
|
117
|
+
/****************************************************/
|
118
|
+
/* ParseDefrule: Coordinates all actions necessary */
|
119
|
+
/* for the parsing and creation of a defrule into */
|
120
|
+
/* the current environment. */
|
121
|
+
/****************************************************/
|
122
|
+
bool ParseDefrule(
|
123
|
+
Environment *theEnv,
|
124
|
+
const char *readSource)
|
125
|
+
{
|
126
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
127
|
+
CLIPSLexeme *ruleName;
|
128
|
+
struct lhsParseNode *theLHS;
|
129
|
+
struct expr *actions;
|
130
|
+
struct token theToken;
|
131
|
+
Defrule *topDisjunct, *tempPtr;
|
132
|
+
struct defruleModule *theModuleItem;
|
133
|
+
bool error;
|
134
|
+
|
135
|
+
/*================================================*/
|
136
|
+
/* Flush the buffer which stores the pretty print */
|
137
|
+
/* representation for a rule. Add the already */
|
138
|
+
/* parsed keyword defrule to this buffer. */
|
139
|
+
/*================================================*/
|
140
|
+
|
141
|
+
SetPPBufferStatus(theEnv,true);
|
142
|
+
FlushPPBuffer(theEnv);
|
143
|
+
SavePPBuffer(theEnv,"(defrule ");
|
144
|
+
|
145
|
+
/*=========================================================*/
|
146
|
+
/* Rules cannot be loaded when a binary load is in effect. */
|
147
|
+
/*=========================================================*/
|
148
|
+
|
149
|
+
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
|
150
|
+
if ((Bloaded(theEnv) == true) && (! ConstructData(theEnv)->CheckSyntaxMode))
|
151
|
+
{
|
152
|
+
CannotLoadWithBloadMessage(theEnv,"defrule");
|
153
|
+
return true;
|
154
|
+
}
|
155
|
+
#endif
|
156
|
+
|
157
|
+
/*================================================*/
|
158
|
+
/* Parse the name and comment fields of the rule, */
|
159
|
+
/* deleting the rule if it already exists. */
|
160
|
+
/*================================================*/
|
161
|
+
|
162
|
+
#if DEBUGGING_FUNCTIONS
|
163
|
+
DefruleData(theEnv)->DeletedRuleDebugFlags = 0;
|
164
|
+
#endif
|
165
|
+
|
166
|
+
ruleName = GetConstructNameAndComment(theEnv,readSource,&theToken,"defrule",
|
167
|
+
(FindConstructFunction *) FindDefruleInModule,
|
168
|
+
(DeleteConstructFunction *) Undefrule,
|
169
|
+
"*",false,
|
170
|
+
true,true,false);
|
171
|
+
|
172
|
+
if (ruleName == NULL) return true;
|
173
|
+
|
174
|
+
/*============================*/
|
175
|
+
/* Parse the LHS of the rule. */
|
176
|
+
/*============================*/
|
177
|
+
|
178
|
+
theLHS = ParseRuleLHS(theEnv,readSource,&theToken,ruleName->contents,&error);
|
179
|
+
if (error)
|
180
|
+
{
|
181
|
+
ReturnPackedExpression(theEnv,PatternData(theEnv)->SalienceExpression);
|
182
|
+
PatternData(theEnv)->SalienceExpression = NULL;
|
183
|
+
return true;
|
184
|
+
}
|
185
|
+
|
186
|
+
/*============================*/
|
187
|
+
/* Parse the RHS of the rule. */
|
188
|
+
/*============================*/
|
189
|
+
|
190
|
+
ClearParsedBindNames(theEnv);
|
191
|
+
ExpressionData(theEnv)->ReturnContext = true;
|
192
|
+
actions = ParseRuleRHS(theEnv,readSource);
|
193
|
+
|
194
|
+
if (actions == NULL)
|
195
|
+
{
|
196
|
+
ReturnPackedExpression(theEnv,PatternData(theEnv)->SalienceExpression);
|
197
|
+
PatternData(theEnv)->SalienceExpression = NULL;
|
198
|
+
ReturnLHSParseNodes(theEnv,theLHS);
|
199
|
+
return true;
|
200
|
+
}
|
201
|
+
|
202
|
+
/*=======================*/
|
203
|
+
/* Process the rule LHS. */
|
204
|
+
/*=======================*/
|
205
|
+
|
206
|
+
topDisjunct = ProcessRuleLHS(theEnv,theLHS,actions,ruleName,&error);
|
207
|
+
|
208
|
+
ReturnExpression(theEnv,actions);
|
209
|
+
ClearParsedBindNames(theEnv);
|
210
|
+
ReturnLHSParseNodes(theEnv,theLHS);
|
211
|
+
|
212
|
+
if (error)
|
213
|
+
{
|
214
|
+
ReturnPackedExpression(theEnv,PatternData(theEnv)->SalienceExpression);
|
215
|
+
PatternData(theEnv)->SalienceExpression = NULL;
|
216
|
+
return true;
|
217
|
+
}
|
218
|
+
|
219
|
+
/*==============================================*/
|
220
|
+
/* If we're only checking syntax, don't add the */
|
221
|
+
/* successfully parsed defrule to the KB. */
|
222
|
+
/*==============================================*/
|
223
|
+
|
224
|
+
if (ConstructData(theEnv)->CheckSyntaxMode)
|
225
|
+
{
|
226
|
+
ReturnPackedExpression(theEnv,PatternData(theEnv)->SalienceExpression);
|
227
|
+
PatternData(theEnv)->SalienceExpression = NULL;
|
228
|
+
return false;
|
229
|
+
}
|
230
|
+
|
231
|
+
PatternData(theEnv)->SalienceExpression = NULL;
|
232
|
+
|
233
|
+
/*======================================*/
|
234
|
+
/* Save the nice printout of the rules. */
|
235
|
+
/*======================================*/
|
236
|
+
|
237
|
+
SavePPBuffer(theEnv,"\n");
|
238
|
+
if (GetConserveMemory(theEnv) == true)
|
239
|
+
{ topDisjunct->header.ppForm = NULL; }
|
240
|
+
else
|
241
|
+
{ topDisjunct->header.ppForm = CopyPPBuffer(theEnv); }
|
242
|
+
|
243
|
+
/*=======================================*/
|
244
|
+
/* Store a pointer to the rule's module. */
|
245
|
+
/*=======================================*/
|
246
|
+
|
247
|
+
theModuleItem = (struct defruleModule *)
|
248
|
+
GetModuleItem(theEnv,NULL,FindModuleItem(theEnv,"defrule")->moduleIndex);
|
249
|
+
|
250
|
+
for (tempPtr = topDisjunct; tempPtr != NULL; tempPtr = tempPtr->disjunct)
|
251
|
+
{
|
252
|
+
tempPtr->header.whichModule = (struct defmoduleItemHeader *) theModuleItem;
|
253
|
+
tempPtr->header.ppForm = topDisjunct->header.ppForm;
|
254
|
+
}
|
255
|
+
|
256
|
+
/*===============================================*/
|
257
|
+
/* Rule completely parsed. Add to list of rules. */
|
258
|
+
/*===============================================*/
|
259
|
+
|
260
|
+
AddToDefruleList(topDisjunct);
|
261
|
+
|
262
|
+
/*========================================================================*/
|
263
|
+
/* If a rule is redefined, then we want to restore its breakpoint status. */
|
264
|
+
/*========================================================================*/
|
265
|
+
|
266
|
+
#if DEBUGGING_FUNCTIONS
|
267
|
+
if (BitwiseTest(DefruleData(theEnv)->DeletedRuleDebugFlags,0))
|
268
|
+
{ SetBreak(topDisjunct); }
|
269
|
+
if (BitwiseTest(DefruleData(theEnv)->DeletedRuleDebugFlags,1) ||
|
270
|
+
(GetWatchItem(theEnv,"activations") == 1))
|
271
|
+
{ DefruleSetWatchActivations(topDisjunct,true); }
|
272
|
+
if (BitwiseTest(DefruleData(theEnv)->DeletedRuleDebugFlags,2) ||
|
273
|
+
(GetWatchItem(theEnv,"rules") == 1))
|
274
|
+
{ DefruleSetWatchFirings(topDisjunct,true); }
|
275
|
+
#endif
|
276
|
+
|
277
|
+
/*================================*/
|
278
|
+
/* Perform the incremental reset. */
|
279
|
+
/*================================*/
|
280
|
+
|
281
|
+
IncrementalReset(theEnv,topDisjunct);
|
282
|
+
|
283
|
+
/*=============================================*/
|
284
|
+
/* Return false to indicate no errors occured. */
|
285
|
+
/*=============================================*/
|
286
|
+
|
287
|
+
#endif
|
288
|
+
return false;
|
289
|
+
}
|
290
|
+
|
291
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY)
|
292
|
+
|
293
|
+
/**************************************************************/
|
294
|
+
/* ProcessRuleLHS: Processes each of the disjuncts of a rule. */
|
295
|
+
/**************************************************************/
|
296
|
+
static Defrule *ProcessRuleLHS(
|
297
|
+
Environment *theEnv,
|
298
|
+
struct lhsParseNode *theLHS,
|
299
|
+
struct expr *actions,
|
300
|
+
CLIPSLexeme *ruleName,
|
301
|
+
bool *error)
|
302
|
+
{
|
303
|
+
struct lhsParseNode *tempNode = NULL;
|
304
|
+
Defrule *topDisjunct = NULL, *currentDisjunct, *lastDisjunct = NULL;
|
305
|
+
struct expr *newActions, *packPtr;
|
306
|
+
int logicalJoin;
|
307
|
+
unsigned short localVarCnt;
|
308
|
+
unsigned short complexity;
|
309
|
+
struct joinNode *lastJoin;
|
310
|
+
bool emptyLHS;
|
311
|
+
|
312
|
+
/*================================================*/
|
313
|
+
/* Initially set the parsing error flag to false. */
|
314
|
+
/*================================================*/
|
315
|
+
|
316
|
+
*error = false;
|
317
|
+
|
318
|
+
/*===========================================================*/
|
319
|
+
/* The top level of the construct representing the LHS of a */
|
320
|
+
/* rule is assumed to be an OR. If the implied OR is at the */
|
321
|
+
/* top level of the pattern construct, then remove it. */
|
322
|
+
/*===========================================================*/
|
323
|
+
|
324
|
+
if (theLHS == NULL)
|
325
|
+
{ emptyLHS = true; }
|
326
|
+
else
|
327
|
+
{
|
328
|
+
emptyLHS = false;
|
329
|
+
if (theLHS->pnType == OR_CE_NODE) theLHS = theLHS->right;
|
330
|
+
}
|
331
|
+
|
332
|
+
/*=========================================*/
|
333
|
+
/* Loop through each disjunct of the rule. */
|
334
|
+
/*=========================================*/
|
335
|
+
|
336
|
+
localVarCnt = CountParsedBindNames(theEnv);
|
337
|
+
|
338
|
+
while ((theLHS != NULL) || (emptyLHS == true))
|
339
|
+
{
|
340
|
+
/*===================================*/
|
341
|
+
/* Analyze the LHS of this disjunct. */
|
342
|
+
/*===================================*/
|
343
|
+
|
344
|
+
if (emptyLHS)
|
345
|
+
{ tempNode = NULL; }
|
346
|
+
else
|
347
|
+
{
|
348
|
+
if (theLHS->pnType == AND_CE_NODE) tempNode = theLHS->right;
|
349
|
+
else if (theLHS->pnType == PATTERN_CE_NODE) tempNode = theLHS;
|
350
|
+
}
|
351
|
+
|
352
|
+
if (VariableAnalysis(theEnv,tempNode))
|
353
|
+
{
|
354
|
+
*error = true;
|
355
|
+
ReturnDefrule(theEnv,topDisjunct);
|
356
|
+
return NULL;
|
357
|
+
}
|
358
|
+
|
359
|
+
/*=========================================*/
|
360
|
+
/* Perform entity dependent post analysis. */
|
361
|
+
/*=========================================*/
|
362
|
+
|
363
|
+
if (PostPatternAnalysis(theEnv,tempNode))
|
364
|
+
{
|
365
|
+
*error = true;
|
366
|
+
ReturnDefrule(theEnv,topDisjunct);
|
367
|
+
return NULL;
|
368
|
+
}
|
369
|
+
|
370
|
+
/*========================================================*/
|
371
|
+
/* Print out developer information if it's being watched. */
|
372
|
+
/*========================================================*/
|
373
|
+
|
374
|
+
#if DEVELOPER && DEBUGGING_FUNCTIONS
|
375
|
+
if (GetWatchItem(theEnv,"rule-analysis") == 1)
|
376
|
+
{ DumpRuleAnalysis(theEnv,tempNode); }
|
377
|
+
#endif
|
378
|
+
|
379
|
+
/*======================================================*/
|
380
|
+
/* Check to see if there are any RHS constraint errors. */
|
381
|
+
/*======================================================*/
|
382
|
+
|
383
|
+
if (CheckRHSForConstraintErrors(theEnv,actions,tempNode))
|
384
|
+
{
|
385
|
+
*error = true;
|
386
|
+
ReturnDefrule(theEnv,topDisjunct);
|
387
|
+
return NULL;
|
388
|
+
}
|
389
|
+
|
390
|
+
/*=================================================*/
|
391
|
+
/* Replace variable references in the RHS with the */
|
392
|
+
/* appropriate variable retrieval functions. */
|
393
|
+
/*=================================================*/
|
394
|
+
|
395
|
+
newActions = CopyExpression(theEnv,actions);
|
396
|
+
if (ReplaceProcVars(theEnv,"RHS of defrule",newActions,NULL,NULL,
|
397
|
+
ReplaceRHSVariable,tempNode))
|
398
|
+
{
|
399
|
+
*error = true;
|
400
|
+
ReturnDefrule(theEnv,topDisjunct);
|
401
|
+
ReturnExpression(theEnv,newActions);
|
402
|
+
return NULL;
|
403
|
+
}
|
404
|
+
|
405
|
+
/*===================================================*/
|
406
|
+
/* Remove any test CEs from the LHS and attach their */
|
407
|
+
/* expression to the closest preceeding non-negated */
|
408
|
+
/* join at the same not/and depth. */
|
409
|
+
/*===================================================*/
|
410
|
+
|
411
|
+
AttachTestCEsToPatternCEs(theEnv,tempNode);
|
412
|
+
|
413
|
+
/*========================================*/
|
414
|
+
/* Check to see that logical CEs are used */
|
415
|
+
/* appropriately in the LHS of the rule. */
|
416
|
+
/*========================================*/
|
417
|
+
|
418
|
+
if ((logicalJoin = LogicalAnalysis(theEnv,tempNode)) < 0)
|
419
|
+
{
|
420
|
+
*error = true;
|
421
|
+
ReturnDefrule(theEnv,topDisjunct);
|
422
|
+
ReturnExpression(theEnv,newActions);
|
423
|
+
return NULL;
|
424
|
+
}
|
425
|
+
|
426
|
+
/*==================================*/
|
427
|
+
/* We're finished for this disjunct */
|
428
|
+
/* if we're only checking syntax. */
|
429
|
+
/*==================================*/
|
430
|
+
|
431
|
+
if (ConstructData(theEnv)->CheckSyntaxMode)
|
432
|
+
{
|
433
|
+
ReturnExpression(theEnv,newActions);
|
434
|
+
if (emptyLHS)
|
435
|
+
{ emptyLHS = false; }
|
436
|
+
else
|
437
|
+
{ theLHS = theLHS->bottom; }
|
438
|
+
continue;
|
439
|
+
}
|
440
|
+
|
441
|
+
/*=================================*/
|
442
|
+
/* Install the disjunct's actions. */
|
443
|
+
/*=================================*/
|
444
|
+
|
445
|
+
ExpressionInstall(theEnv,newActions);
|
446
|
+
packPtr = PackExpression(theEnv,newActions);
|
447
|
+
ReturnExpression(theEnv,newActions);
|
448
|
+
|
449
|
+
/*===============================================================*/
|
450
|
+
/* Create the pattern and join data structures for the new rule. */
|
451
|
+
/*===============================================================*/
|
452
|
+
|
453
|
+
lastJoin = ConstructJoins(theEnv,logicalJoin,tempNode,1,NULL,true,true);
|
454
|
+
|
455
|
+
/*===================================================================*/
|
456
|
+
/* Determine the rule's complexity for use with conflict resolution. */
|
457
|
+
/*===================================================================*/
|
458
|
+
|
459
|
+
complexity = RuleComplexity(theEnv,tempNode);
|
460
|
+
|
461
|
+
/*=====================================================*/
|
462
|
+
/* Create the defrule data structure for this disjunct */
|
463
|
+
/* and put it in the list of disjuncts for this rule. */
|
464
|
+
/*=====================================================*/
|
465
|
+
|
466
|
+
currentDisjunct = CreateNewDisjunct(theEnv,ruleName,localVarCnt,packPtr,complexity,
|
467
|
+
(unsigned) logicalJoin,lastJoin);
|
468
|
+
|
469
|
+
/*============================================================*/
|
470
|
+
/* Place the disjunct in the list of disjuncts for this rule. */
|
471
|
+
/* If the disjunct is the first disjunct, then increment the */
|
472
|
+
/* reference counts for the dynamic salience (the expression */
|
473
|
+
/* for the dynamic salience is only stored with the first */
|
474
|
+
/* disjuncts and the other disjuncts refer back to the first */
|
475
|
+
/* disjunct for their dynamic salience value. */
|
476
|
+
/*============================================================*/
|
477
|
+
|
478
|
+
if (topDisjunct == NULL)
|
479
|
+
{
|
480
|
+
topDisjunct = currentDisjunct;
|
481
|
+
ExpressionInstall(theEnv,topDisjunct->dynamicSalience);
|
482
|
+
}
|
483
|
+
else lastDisjunct->disjunct = currentDisjunct;
|
484
|
+
|
485
|
+
/*===========================================*/
|
486
|
+
/* Move on to the next disjunct of the rule. */
|
487
|
+
/*===========================================*/
|
488
|
+
|
489
|
+
lastDisjunct = currentDisjunct;
|
490
|
+
|
491
|
+
if (emptyLHS)
|
492
|
+
{ emptyLHS = false; }
|
493
|
+
else
|
494
|
+
{ theLHS = theLHS->bottom; }
|
495
|
+
}
|
496
|
+
|
497
|
+
return(topDisjunct);
|
498
|
+
}
|
499
|
+
|
500
|
+
/************************************************************************/
|
501
|
+
/* CreateNewDisjunct: Creates and initializes a defrule data structure. */
|
502
|
+
/************************************************************************/
|
503
|
+
static Defrule *CreateNewDisjunct(
|
504
|
+
Environment *theEnv,
|
505
|
+
CLIPSLexeme *ruleName,
|
506
|
+
unsigned short localVarCnt,
|
507
|
+
struct expr *theActions,
|
508
|
+
unsigned int complexity,
|
509
|
+
unsigned logicalJoin,
|
510
|
+
struct joinNode *lastJoin)
|
511
|
+
{
|
512
|
+
struct joinNode *tempJoin;
|
513
|
+
Defrule *newDisjunct;
|
514
|
+
|
515
|
+
/*===================================================*/
|
516
|
+
/* Create and initialize the defrule data structure. */
|
517
|
+
/*===================================================*/
|
518
|
+
|
519
|
+
newDisjunct = get_struct(theEnv,defrule);
|
520
|
+
newDisjunct->header.ppForm = NULL;
|
521
|
+
newDisjunct->header.next = NULL;
|
522
|
+
newDisjunct->header.usrData = NULL;
|
523
|
+
newDisjunct->logicalJoin = NULL;
|
524
|
+
newDisjunct->disjunct = NULL;
|
525
|
+
newDisjunct->header.constructType = DEFRULE;
|
526
|
+
newDisjunct->header.env = theEnv;
|
527
|
+
newDisjunct->header.name = ruleName;
|
528
|
+
IncrementLexemeCount(newDisjunct->header.name);
|
529
|
+
newDisjunct->actions = theActions;
|
530
|
+
newDisjunct->salience = PatternData(theEnv)->GlobalSalience;
|
531
|
+
newDisjunct->afterBreakpoint = 0;
|
532
|
+
newDisjunct->watchActivation = 0;
|
533
|
+
newDisjunct->watchFiring = 0;
|
534
|
+
newDisjunct->executing = 0;
|
535
|
+
newDisjunct->complexity = complexity;
|
536
|
+
newDisjunct->autoFocus = PatternData(theEnv)->GlobalAutoFocus;
|
537
|
+
newDisjunct->dynamicSalience = PatternData(theEnv)->SalienceExpression;
|
538
|
+
newDisjunct->localVarCnt = localVarCnt;
|
539
|
+
|
540
|
+
/*=====================================*/
|
541
|
+
/* Add a pointer to the rule's module. */
|
542
|
+
/*=====================================*/
|
543
|
+
|
544
|
+
newDisjunct->header.whichModule =
|
545
|
+
(struct defmoduleItemHeader *)
|
546
|
+
GetModuleItem(theEnv,NULL,FindModuleItem(theEnv,"defrule")->moduleIndex);
|
547
|
+
|
548
|
+
/*============================================================*/
|
549
|
+
/* Attach the rule's last join to the defrule data structure. */
|
550
|
+
/*============================================================*/
|
551
|
+
|
552
|
+
lastJoin->ruleToActivate = newDisjunct;
|
553
|
+
newDisjunct->lastJoin = lastJoin;
|
554
|
+
|
555
|
+
/*=================================================*/
|
556
|
+
/* Determine the rule's logical join if it exists. */
|
557
|
+
/*=================================================*/
|
558
|
+
|
559
|
+
tempJoin = lastJoin;
|
560
|
+
while (tempJoin != NULL)
|
561
|
+
{
|
562
|
+
if (tempJoin->depth == logicalJoin)
|
563
|
+
{
|
564
|
+
newDisjunct->logicalJoin = tempJoin;
|
565
|
+
tempJoin->logicalJoin = true;
|
566
|
+
}
|
567
|
+
tempJoin = tempJoin->lastLevel;
|
568
|
+
}
|
569
|
+
|
570
|
+
/*==================================================*/
|
571
|
+
/* Return the newly created defrule data structure. */
|
572
|
+
/*==================================================*/
|
573
|
+
|
574
|
+
return(newDisjunct);
|
575
|
+
}
|
576
|
+
|
577
|
+
/****************************************************************/
|
578
|
+
/* ReplaceExpressionVariables: Replaces all symbolic references */
|
579
|
+
/* to variables (local and global) found in an expression on */
|
580
|
+
/* the RHS of a rule with expressions containing function */
|
581
|
+
/* calls to retrieve the variable's value. Makes the final */
|
582
|
+
/* modifications necessary for handling the modify and */
|
583
|
+
/* duplicate commands. */
|
584
|
+
/****************************************************************/
|
585
|
+
static int ReplaceRHSVariable(
|
586
|
+
Environment *theEnv,
|
587
|
+
struct expr *list,
|
588
|
+
void *VtheLHS)
|
589
|
+
{
|
590
|
+
struct lhsParseNode *theVariable;
|
591
|
+
|
592
|
+
/*=======================================*/
|
593
|
+
/* Handle modify and duplicate commands. */
|
594
|
+
/*=======================================*/
|
595
|
+
|
596
|
+
#if DEFTEMPLATE_CONSTRUCT
|
597
|
+
if (list->type == FCALL)
|
598
|
+
{
|
599
|
+
if (list->value == (void *) FindFunction(theEnv,"modify"))
|
600
|
+
{
|
601
|
+
if (UpdateModifyDuplicate(theEnv,list,"modify",VtheLHS) == false)
|
602
|
+
{ return -1; }
|
603
|
+
}
|
604
|
+
else if (list->value == (void *) FindFunction(theEnv,"duplicate"))
|
605
|
+
{
|
606
|
+
if (UpdateModifyDuplicate(theEnv,list,"duplicate",VtheLHS) == false)
|
607
|
+
{ return -1; }
|
608
|
+
}
|
609
|
+
|
610
|
+
return 0;
|
611
|
+
}
|
612
|
+
|
613
|
+
#endif
|
614
|
+
|
615
|
+
if ((list->type != SF_VARIABLE) && (list->type != MF_VARIABLE))
|
616
|
+
{ return 0; }
|
617
|
+
|
618
|
+
/*===============================================================*/
|
619
|
+
/* Check to see if the variable is bound on the LHS of the rule. */
|
620
|
+
/*===============================================================*/
|
621
|
+
|
622
|
+
theVariable = FindVariable(list->lexemeValue,(struct lhsParseNode *) VtheLHS);
|
623
|
+
if (theVariable == NULL) return 0;
|
624
|
+
|
625
|
+
/*================================================*/
|
626
|
+
/* Replace the variable reference with a function */
|
627
|
+
/* call to retrieve the variable. */
|
628
|
+
/*================================================*/
|
629
|
+
|
630
|
+
if (theVariable->patternType != NULL)
|
631
|
+
{ (*theVariable->patternType->replaceGetJNValueFunction)(theEnv,list,theVariable,LHS); }
|
632
|
+
else
|
633
|
+
{ return 0; }
|
634
|
+
|
635
|
+
/*==============================================================*/
|
636
|
+
/* Return 1 to indicate the variable was successfully replaced. */
|
637
|
+
/*==============================================================*/
|
638
|
+
|
639
|
+
return 1;
|
640
|
+
}
|
641
|
+
|
642
|
+
/*******************************************************/
|
643
|
+
/* ParseRuleRHS: Coordinates all the actions necessary */
|
644
|
+
/* for parsing the RHS of a rule. */
|
645
|
+
/*******************************************************/
|
646
|
+
static struct expr *ParseRuleRHS(
|
647
|
+
Environment *theEnv,
|
648
|
+
const char *readSource)
|
649
|
+
{
|
650
|
+
struct expr *actions;
|
651
|
+
struct token theToken;
|
652
|
+
|
653
|
+
/*=========================================================*/
|
654
|
+
/* Process the actions on the right hand side of the rule. */
|
655
|
+
/*=========================================================*/
|
656
|
+
|
657
|
+
SavePPBuffer(theEnv,"\n ");
|
658
|
+
SetIndentDepth(theEnv,3);
|
659
|
+
|
660
|
+
actions = GroupActions(theEnv,readSource,&theToken,true,NULL,false);
|
661
|
+
|
662
|
+
if (actions == NULL) return NULL;
|
663
|
+
|
664
|
+
/*=============================*/
|
665
|
+
/* Reformat the closing token. */
|
666
|
+
/*=============================*/
|
667
|
+
|
668
|
+
PPBackup(theEnv);
|
669
|
+
PPBackup(theEnv);
|
670
|
+
SavePPBuffer(theEnv,theToken.printForm);
|
671
|
+
|
672
|
+
/*======================================================*/
|
673
|
+
/* Check for the closing right parenthesis of the rule. */
|
674
|
+
/*======================================================*/
|
675
|
+
|
676
|
+
if (theToken.tknType != RIGHT_PARENTHESIS_TOKEN)
|
677
|
+
{
|
678
|
+
SyntaxErrorMessage(theEnv,"defrule");
|
679
|
+
ReturnExpression(theEnv,actions);
|
680
|
+
return NULL;
|
681
|
+
}
|
682
|
+
|
683
|
+
/*========================*/
|
684
|
+
/* Return the rule's RHS. */
|
685
|
+
/*========================*/
|
686
|
+
|
687
|
+
return(actions);
|
688
|
+
}
|
689
|
+
|
690
|
+
/************************************************************/
|
691
|
+
/* RuleComplexity: Returns the complexity of a rule for use */
|
692
|
+
/* by the LEX and MEA conflict resolution strategies. */
|
693
|
+
/************************************************************/
|
694
|
+
static unsigned short RuleComplexity(
|
695
|
+
Environment *theEnv,
|
696
|
+
struct lhsParseNode *theLHS)
|
697
|
+
{
|
698
|
+
struct lhsParseNode *thePattern, *tempPattern;
|
699
|
+
unsigned short complexity = 0;
|
700
|
+
|
701
|
+
while (theLHS != NULL)
|
702
|
+
{
|
703
|
+
complexity += 1; /* Add 1 for each pattern. */
|
704
|
+
complexity += ExpressionComplexity(theEnv,theLHS->networkTest);
|
705
|
+
thePattern = theLHS->right;
|
706
|
+
while (thePattern != NULL)
|
707
|
+
{
|
708
|
+
if (thePattern->multifieldSlot)
|
709
|
+
{
|
710
|
+
tempPattern = thePattern->bottom;
|
711
|
+
while (tempPattern != NULL)
|
712
|
+
{
|
713
|
+
complexity += ExpressionComplexity(theEnv,tempPattern->networkTest);
|
714
|
+
tempPattern = tempPattern->right;
|
715
|
+
}
|
716
|
+
}
|
717
|
+
else
|
718
|
+
{ complexity += ExpressionComplexity(theEnv,thePattern->networkTest); }
|
719
|
+
thePattern = thePattern->right;
|
720
|
+
}
|
721
|
+
theLHS = theLHS->bottom;
|
722
|
+
}
|
723
|
+
|
724
|
+
return complexity;
|
725
|
+
}
|
726
|
+
|
727
|
+
/********************************************************************/
|
728
|
+
/* ExpressionComplexity: Determines the complexity of a expression. */
|
729
|
+
/********************************************************************/
|
730
|
+
static unsigned short ExpressionComplexity(
|
731
|
+
Environment *theEnv,
|
732
|
+
struct expr *exprPtr)
|
733
|
+
{
|
734
|
+
unsigned short complexity = 0;
|
735
|
+
|
736
|
+
while (exprPtr != NULL)
|
737
|
+
{
|
738
|
+
if (exprPtr->type == FCALL)
|
739
|
+
{
|
740
|
+
/*=========================================*/
|
741
|
+
/* Logical combinations do not add to the */
|
742
|
+
/* complexity, but their arguments do. */
|
743
|
+
/*=========================================*/
|
744
|
+
|
745
|
+
if ((exprPtr->value == ExpressionData(theEnv)->PTR_AND) ||
|
746
|
+
(exprPtr->value == ExpressionData(theEnv)->PTR_NOT) ||
|
747
|
+
(exprPtr->value == ExpressionData(theEnv)->PTR_OR))
|
748
|
+
{ complexity += ExpressionComplexity(theEnv,exprPtr->argList); }
|
749
|
+
|
750
|
+
/*=========================================*/
|
751
|
+
/* else other function calls increase the */
|
752
|
+
/* complexity, but their arguments do not. */
|
753
|
+
/*=========================================*/
|
754
|
+
|
755
|
+
else
|
756
|
+
{ complexity++; }
|
757
|
+
}
|
758
|
+
else if ((EvaluationData(theEnv)->PrimitivesArray[exprPtr->type] != NULL) ?
|
759
|
+
EvaluationData(theEnv)->PrimitivesArray[exprPtr->type]->addsToRuleComplexity : false)
|
760
|
+
{ complexity++; }
|
761
|
+
|
762
|
+
exprPtr = exprPtr->nextArg;
|
763
|
+
}
|
764
|
+
|
765
|
+
return complexity;
|
766
|
+
}
|
767
|
+
|
768
|
+
/********************************************/
|
769
|
+
/* LogicalAnalysis: Analyzes the use of the */
|
770
|
+
/* logical CE within the LHS of a rule. */
|
771
|
+
/********************************************/
|
772
|
+
static int LogicalAnalysis(
|
773
|
+
Environment *theEnv,
|
774
|
+
struct lhsParseNode *patternList)
|
775
|
+
{
|
776
|
+
bool firstLogical, logicalsFound = false;
|
777
|
+
int logicalJoin = 1;
|
778
|
+
bool gap = false;
|
779
|
+
|
780
|
+
if (patternList == NULL) return 0;
|
781
|
+
|
782
|
+
firstLogical = patternList->logical;
|
783
|
+
|
784
|
+
/*===================================================*/
|
785
|
+
/* Loop through each pattern in the LHS of the rule. */
|
786
|
+
/*===================================================*/
|
787
|
+
|
788
|
+
for (;
|
789
|
+
patternList != NULL;
|
790
|
+
patternList = patternList->bottom)
|
791
|
+
{
|
792
|
+
/*=======================================*/
|
793
|
+
/* Skip anything that isn't a pattern CE */
|
794
|
+
/* or is embedded within a not/and CE. */
|
795
|
+
/*=======================================*/
|
796
|
+
|
797
|
+
if (((patternList->pnType != PATTERN_CE_NODE) &&
|
798
|
+
(patternList->pnType != TEST_CE_NODE)) ||
|
799
|
+
(patternList->endNandDepth != 1))
|
800
|
+
{ continue; }
|
801
|
+
|
802
|
+
/*=====================================================*/
|
803
|
+
/* If the pattern CE is not contained within a logical */
|
804
|
+
/* CE, then set the gap flag to true indicating that */
|
805
|
+
/* any subsequent pattern CE found within a logical CE */
|
806
|
+
/* represents a gap between logical CEs which is an */
|
807
|
+
/* error. */
|
808
|
+
/*=====================================================*/
|
809
|
+
|
810
|
+
if (patternList->logical == false)
|
811
|
+
{
|
812
|
+
gap = true;
|
813
|
+
continue;
|
814
|
+
}
|
815
|
+
|
816
|
+
/*=================================================*/
|
817
|
+
/* If a logical CE is encountered and the first CE */
|
818
|
+
/* of the rule isn't a logical CE, then indicate */
|
819
|
+
/* that the first CE must be a logical CE. */
|
820
|
+
/*=================================================*/
|
821
|
+
|
822
|
+
if (! firstLogical)
|
823
|
+
{
|
824
|
+
PrintErrorID(theEnv,"RULEPSR",1,true);
|
825
|
+
WriteString(theEnv,STDERR,"Logical CEs must be placed first in a rule\n");
|
826
|
+
return -1;
|
827
|
+
}
|
828
|
+
|
829
|
+
/*===================================================*/
|
830
|
+
/* If a break within the logical CEs was found and a */
|
831
|
+
/* new logical CE is encountered, then indicate that */
|
832
|
+
/* there can't be any gaps between logical CEs. */
|
833
|
+
/*===================================================*/
|
834
|
+
|
835
|
+
if (gap)
|
836
|
+
{
|
837
|
+
PrintErrorID(theEnv,"RULEPSR",2,true);
|
838
|
+
WriteString(theEnv,STDERR,"Gaps may not exist between logical CEs\n");
|
839
|
+
return -1;
|
840
|
+
}
|
841
|
+
|
842
|
+
/*===========================================*/
|
843
|
+
/* Increment the count of logical CEs found. */
|
844
|
+
/*===========================================*/
|
845
|
+
|
846
|
+
if (patternList->pnType == PATTERN_CE_NODE)
|
847
|
+
{ logicalJoin++; }
|
848
|
+
else if (logicalJoin == 1)
|
849
|
+
{ logicalJoin++; }
|
850
|
+
|
851
|
+
logicalsFound = true;
|
852
|
+
}
|
853
|
+
|
854
|
+
/*============================================*/
|
855
|
+
/* If logical CEs were found, then return the */
|
856
|
+
/* join number where the logical information */
|
857
|
+
/* will be stored in the join network. */
|
858
|
+
/*============================================*/
|
859
|
+
|
860
|
+
if (logicalsFound)
|
861
|
+
{ return logicalJoin; }
|
862
|
+
|
863
|
+
/*=============================*/
|
864
|
+
/* Return zero indicating that */
|
865
|
+
/* no logical CE was found. */
|
866
|
+
/*=============================*/
|
867
|
+
|
868
|
+
return 0;
|
869
|
+
}
|
870
|
+
|
871
|
+
/*****************************************************************/
|
872
|
+
/* FindVariable: Searches for the last occurence of a variable */
|
873
|
+
/* in the LHS of a rule that is visible from the RHS of a rule. */
|
874
|
+
/* The last occurence of the variable on the LHS side of the */
|
875
|
+
/* rule will have the strictest constraints (because it will */
|
876
|
+
/* have been intersected with all of the other constraints for */
|
877
|
+
/* the variable on the LHS of the rule). The strictest */
|
878
|
+
/* constraints are useful for performing type checking on the */
|
879
|
+
/* RHS of the rule. */
|
880
|
+
/*****************************************************************/
|
881
|
+
struct lhsParseNode *FindVariable(
|
882
|
+
CLIPSLexeme *name,
|
883
|
+
struct lhsParseNode *theLHS)
|
884
|
+
{
|
885
|
+
struct lhsParseNode *theFields, *tmpFields = NULL;
|
886
|
+
struct lhsParseNode *theReturnValue = NULL;
|
887
|
+
|
888
|
+
/*==============================================*/
|
889
|
+
/* Loop through each CE in the LHS of the rule. */
|
890
|
+
/*==============================================*/
|
891
|
+
|
892
|
+
for (;
|
893
|
+
theLHS != NULL;
|
894
|
+
theLHS = theLHS->bottom)
|
895
|
+
{
|
896
|
+
/*==========================================*/
|
897
|
+
/* Don't bother searching for the variable */
|
898
|
+
/* in anything other than a pattern CE that */
|
899
|
+
/* is not contained within a not CE. */
|
900
|
+
/*==========================================*/
|
901
|
+
|
902
|
+
if ((theLHS->pnType != PATTERN_CE_NODE) ||
|
903
|
+
(theLHS->negated == true) ||
|
904
|
+
(theLHS->exists == true) ||
|
905
|
+
(theLHS->beginNandDepth > 1))
|
906
|
+
{ continue; }
|
907
|
+
|
908
|
+
/*=====================================*/
|
909
|
+
/* Check the pattern address variable. */
|
910
|
+
/*=====================================*/
|
911
|
+
|
912
|
+
if (theLHS->value == (void *) name)
|
913
|
+
{ theReturnValue = theLHS; }
|
914
|
+
|
915
|
+
/*============================================*/
|
916
|
+
/* Check for the variable inside the pattern. */
|
917
|
+
/*============================================*/
|
918
|
+
|
919
|
+
theFields = theLHS->right;
|
920
|
+
while (theFields != NULL)
|
921
|
+
{
|
922
|
+
/*=================================================*/
|
923
|
+
/* Go one level deeper to check a multifield slot. */
|
924
|
+
/*=================================================*/
|
925
|
+
|
926
|
+
if (theFields->multifieldSlot)
|
927
|
+
{
|
928
|
+
tmpFields = theFields;
|
929
|
+
theFields = theFields->bottom;
|
930
|
+
}
|
931
|
+
|
932
|
+
/*=================================*/
|
933
|
+
/* See if the field being examined */
|
934
|
+
/* is the variable being sought. */
|
935
|
+
/*=================================*/
|
936
|
+
|
937
|
+
if (theFields == NULL)
|
938
|
+
{ /* Do Nothing */ }
|
939
|
+
else if (((theFields->pnType == SF_VARIABLE_NODE) ||
|
940
|
+
(theFields->pnType == MF_VARIABLE_NODE)) &&
|
941
|
+
(theFields->value == (void *) name))
|
942
|
+
{ theReturnValue = theFields; }
|
943
|
+
|
944
|
+
/*============================*/
|
945
|
+
/* Move on to the next field. */
|
946
|
+
/*============================*/
|
947
|
+
|
948
|
+
if (theFields == NULL)
|
949
|
+
{
|
950
|
+
theFields = tmpFields;
|
951
|
+
tmpFields = NULL;
|
952
|
+
}
|
953
|
+
else if ((theFields->right == NULL) && (tmpFields != NULL))
|
954
|
+
{
|
955
|
+
theFields = tmpFields;
|
956
|
+
tmpFields = NULL;
|
957
|
+
}
|
958
|
+
theFields = theFields->right;
|
959
|
+
}
|
960
|
+
}
|
961
|
+
|
962
|
+
/*=========================================================*/
|
963
|
+
/* Return a pointer to the LHS location where the variable */
|
964
|
+
/* was found (or a NULL pointer if it wasn't). */
|
965
|
+
/*=========================================================*/
|
966
|
+
|
967
|
+
return(theReturnValue);
|
968
|
+
}
|
969
|
+
|
970
|
+
/**********************************************************/
|
971
|
+
/* AddToDefruleList: Adds a defrule to the list of rules. */
|
972
|
+
/**********************************************************/
|
973
|
+
static void AddToDefruleList(
|
974
|
+
Defrule *rulePtr)
|
975
|
+
{
|
976
|
+
Defrule *tempRule;
|
977
|
+
struct defruleModule *theModuleItem;
|
978
|
+
|
979
|
+
theModuleItem = (struct defruleModule *) rulePtr->header.whichModule;
|
980
|
+
|
981
|
+
if (theModuleItem->header.lastItem == NULL)
|
982
|
+
{ theModuleItem->header.firstItem = &rulePtr->header; }
|
983
|
+
else
|
984
|
+
{
|
985
|
+
tempRule = (Defrule *) theModuleItem->header.lastItem; // Note: Only the first disjunct
|
986
|
+
tempRule->header.next = &rulePtr->header; // points to the next rule
|
987
|
+
}
|
988
|
+
|
989
|
+
theModuleItem->header.lastItem = &rulePtr->header;
|
990
|
+
}
|
991
|
+
|
992
|
+
#if DEVELOPER && DEBUGGING_FUNCTIONS
|
993
|
+
|
994
|
+
/************************************************************/
|
995
|
+
/* DumpRuleAnalysis: Displays the information about network */
|
996
|
+
/* expressions generated from the analysis of the rule. */
|
997
|
+
/************************************************************/
|
998
|
+
void DumpRuleAnalysis(
|
999
|
+
Environment *theEnv,
|
1000
|
+
struct lhsParseNode *tempNode)
|
1001
|
+
{
|
1002
|
+
struct lhsParseNode *traceNode;
|
1003
|
+
char buffer[20];
|
1004
|
+
|
1005
|
+
WriteString(theEnv,STDOUT,"\n");
|
1006
|
+
for (traceNode = tempNode; traceNode != NULL; traceNode = traceNode->bottom)
|
1007
|
+
{
|
1008
|
+
if (traceNode->userCE)
|
1009
|
+
{ gensprintf(buffer,sizeof(buffer),"UCE %2d (%2d %2d): ",traceNode->whichCE,traceNode->beginNandDepth,traceNode->endNandDepth); }
|
1010
|
+
else
|
1011
|
+
{ gensprintf(buffer,sizeof(buffer),"SCE %2d (%2d %2d): ",traceNode->whichCE,traceNode->beginNandDepth,traceNode->endNandDepth); }
|
1012
|
+
|
1013
|
+
WriteString(theEnv,STDOUT,buffer);
|
1014
|
+
|
1015
|
+
PrintExpression(theEnv,STDOUT,traceNode->networkTest);
|
1016
|
+
WriteString(theEnv,STDOUT,"\n");
|
1017
|
+
|
1018
|
+
if (traceNode->externalNetworkTest != NULL)
|
1019
|
+
{
|
1020
|
+
WriteString(theEnv,STDOUT," ENT: ");
|
1021
|
+
PrintExpression(theEnv,STDOUT,traceNode->externalNetworkTest);
|
1022
|
+
WriteString(theEnv,STDOUT,"\n");
|
1023
|
+
}
|
1024
|
+
|
1025
|
+
if (traceNode->secondaryNetworkTest != NULL)
|
1026
|
+
{
|
1027
|
+
WriteString(theEnv,STDOUT," SNT: ");
|
1028
|
+
PrintExpression(theEnv,STDOUT,traceNode->secondaryNetworkTest);
|
1029
|
+
WriteString(theEnv,STDOUT,"\n");
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
if (traceNode->externalRightHash != NULL)
|
1033
|
+
{
|
1034
|
+
WriteString(theEnv,STDOUT," ERH: ");
|
1035
|
+
PrintExpression(theEnv,STDOUT,traceNode->externalRightHash);
|
1036
|
+
WriteString(theEnv,STDOUT,"\n");
|
1037
|
+
}
|
1038
|
+
|
1039
|
+
if (traceNode->externalLeftHash != NULL)
|
1040
|
+
{
|
1041
|
+
WriteString(theEnv,STDOUT," ELH: ");
|
1042
|
+
PrintExpression(theEnv,STDOUT,traceNode->externalLeftHash);
|
1043
|
+
WriteString(theEnv,STDOUT,"\n");
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
if (traceNode->leftHash != NULL)
|
1047
|
+
{
|
1048
|
+
WriteString(theEnv,STDOUT," LH: ");
|
1049
|
+
PrintExpression(theEnv,STDOUT,traceNode->leftHash);
|
1050
|
+
WriteString(theEnv,STDOUT,"\n");
|
1051
|
+
}
|
1052
|
+
|
1053
|
+
if (traceNode->rightHash != NULL)
|
1054
|
+
{
|
1055
|
+
WriteString(theEnv,STDOUT," RH: ");
|
1056
|
+
PrintExpression(theEnv,STDOUT,traceNode->rightHash);
|
1057
|
+
WriteString(theEnv,STDOUT,"\n");
|
1058
|
+
}
|
1059
|
+
|
1060
|
+
if (traceNode->betaHash != NULL)
|
1061
|
+
{
|
1062
|
+
WriteString(theEnv,STDOUT," BH: ");
|
1063
|
+
PrintExpression(theEnv,STDOUT,traceNode->betaHash);
|
1064
|
+
WriteString(theEnv,STDOUT,"\n");
|
1065
|
+
}
|
1066
|
+
}
|
1067
|
+
}
|
1068
|
+
#endif
|
1069
|
+
|
1070
|
+
#endif /* (! RUN_TIME) && (! BLOAD_ONLY) */
|
1071
|
+
|
1072
|
+
#endif /* DEFRULE_CONSTRUCT */
|
1073
|
+
|