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,1142 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.40 06/12/19 */
|
5
|
+
/* */
|
6
|
+
/* ANALYSIS MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: Analyzes LHS patterns to check for semantic */
|
11
|
+
/* errors and to determine variable comparisons and other */
|
12
|
+
/* tests which must be performed either in the pattern or */
|
13
|
+
/* join networks. */
|
14
|
+
/* */
|
15
|
+
/* Principal Programmer(s): */
|
16
|
+
/* Gary D. Riley */
|
17
|
+
/* */
|
18
|
+
/* Contributing Programmer(s): */
|
19
|
+
/* */
|
20
|
+
/* Revision History: */
|
21
|
+
/* */
|
22
|
+
/* 6.24: Renamed BOOLEAN macro type to intBool. */
|
23
|
+
/* */
|
24
|
+
/* 6.30: Join network rework and optimizations. */
|
25
|
+
/* */
|
26
|
+
/* 6.31: Memory leak fix for multislot pattern with */
|
27
|
+
/* no constraints. */
|
28
|
+
/* */
|
29
|
+
/* 6.40: Pragma once and other inclusion changes. */
|
30
|
+
/* */
|
31
|
+
/* Added support for booleans with <stdbool.h>. */
|
32
|
+
/* */
|
33
|
+
/* Removed use of void pointers for specific */
|
34
|
+
/* data structures. */
|
35
|
+
/* */
|
36
|
+
/* Static constraint checking is always enabled. */
|
37
|
+
/* */
|
38
|
+
/*************************************************************/
|
39
|
+
|
40
|
+
#include "setup.h"
|
41
|
+
|
42
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
|
43
|
+
|
44
|
+
#include <stdio.h>
|
45
|
+
|
46
|
+
#include "constant.h"
|
47
|
+
#include "cstrnchk.h"
|
48
|
+
#include "cstrnutl.h"
|
49
|
+
#include "cstrnops.h"
|
50
|
+
#include "exprnpsr.h"
|
51
|
+
#include "generate.h"
|
52
|
+
#include "memalloc.h"
|
53
|
+
#include "modulutl.h"
|
54
|
+
#include "pattern.h"
|
55
|
+
#include "prntutil.h"
|
56
|
+
#include "reorder.h"
|
57
|
+
#include "router.h"
|
58
|
+
#include "rulecstr.h"
|
59
|
+
#include "ruledef.h"
|
60
|
+
#include "rulepsr.h"
|
61
|
+
#include "symbol.h"
|
62
|
+
#include "watch.h"
|
63
|
+
|
64
|
+
#include "analysis.h"
|
65
|
+
|
66
|
+
/***************************************/
|
67
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
68
|
+
/***************************************/
|
69
|
+
|
70
|
+
static bool GetVariables(Environment *,struct lhsParseNode *,ParseNodeType,struct nandFrame *);
|
71
|
+
static bool UnboundVariablesInPattern(Environment *,struct lhsParseNode *,unsigned short);
|
72
|
+
static bool PropagateVariableToNodes(Environment *,struct lhsParseNode *,ParseNodeType,
|
73
|
+
CLIPSLexeme *,struct lhsParseNode *,
|
74
|
+
int,bool,bool);
|
75
|
+
static struct lhsParseNode *CheckExpression(Environment *,struct lhsParseNode *,struct lhsParseNode *,
|
76
|
+
unsigned short,CLIPSLexeme *,unsigned short);
|
77
|
+
static void VariableReferenceErrorMessage(Environment *,
|
78
|
+
CLIPSLexeme *,
|
79
|
+
struct lhsParseNode *,
|
80
|
+
int,
|
81
|
+
CLIPSLexeme *,
|
82
|
+
int);
|
83
|
+
static bool ProcessField(Environment *,
|
84
|
+
struct lhsParseNode *,
|
85
|
+
struct lhsParseNode *,
|
86
|
+
struct lhsParseNode *,
|
87
|
+
ParseNodeType,
|
88
|
+
struct nandFrame *);
|
89
|
+
static bool ProcessVariable(Environment *,
|
90
|
+
struct lhsParseNode *,
|
91
|
+
struct lhsParseNode *,
|
92
|
+
struct lhsParseNode *,
|
93
|
+
ParseNodeType,
|
94
|
+
struct nandFrame *);
|
95
|
+
static void VariableMixingErrorMessage(Environment *,CLIPSLexeme *);
|
96
|
+
static bool PropagateVariableDriver(Environment *,
|
97
|
+
struct lhsParseNode *,
|
98
|
+
struct lhsParseNode *,
|
99
|
+
struct lhsParseNode *,
|
100
|
+
ParseNodeType,CLIPSLexeme *,
|
101
|
+
struct lhsParseNode *,
|
102
|
+
bool,ParseNodeType);
|
103
|
+
static bool TestCEAnalysis(Environment *,struct lhsParseNode *,struct lhsParseNode *,bool,bool *,struct nandFrame *);
|
104
|
+
static void ReleaseNandFrames(Environment *,struct nandFrame *);
|
105
|
+
|
106
|
+
/******************************************************************/
|
107
|
+
/* VariableAnalysis: Propagates variables references to other */
|
108
|
+
/* variables in the LHS and determines if there are any illegal */
|
109
|
+
/* variable references (e.g. referring to an unbound variable). */
|
110
|
+
/* The propagation of variable references simply means all */
|
111
|
+
/* subsequent references of a variable are made to "point" back */
|
112
|
+
/* to the variable being propagated. */
|
113
|
+
/******************************************************************/
|
114
|
+
bool VariableAnalysis(
|
115
|
+
Environment *theEnv,
|
116
|
+
struct lhsParseNode *patternPtr)
|
117
|
+
{
|
118
|
+
bool errorFlag = false;
|
119
|
+
struct nandFrame *theNandFrames = NULL, *tempNandPtr;
|
120
|
+
int currentDepth = 1;
|
121
|
+
|
122
|
+
/*======================================================*/
|
123
|
+
/* Loop through all of the CEs in the rule to determine */
|
124
|
+
/* which variables refer to other variables and whether */
|
125
|
+
/* any semantic errors exist when refering to variables */
|
126
|
+
/* (such as referring to a variable that was not */
|
127
|
+
/* previously bound). */
|
128
|
+
/*======================================================*/
|
129
|
+
|
130
|
+
while (patternPtr != NULL)
|
131
|
+
{
|
132
|
+
/*==================================*/
|
133
|
+
/* If the nand depth is increasing, */
|
134
|
+
/* create a new nand frame. */
|
135
|
+
/*==================================*/
|
136
|
+
|
137
|
+
while (patternPtr->beginNandDepth > currentDepth)
|
138
|
+
{
|
139
|
+
tempNandPtr = get_struct(theEnv,nandFrame);
|
140
|
+
tempNandPtr->nandCE = patternPtr;
|
141
|
+
tempNandPtr->depth = currentDepth;
|
142
|
+
tempNandPtr->next = theNandFrames;
|
143
|
+
theNandFrames = tempNandPtr;
|
144
|
+
currentDepth++;
|
145
|
+
}
|
146
|
+
|
147
|
+
/*=========================================================*/
|
148
|
+
/* If a pattern CE is encountered, propagate any variables */
|
149
|
+
/* found in the pattern and note any illegal references to */
|
150
|
+
/* other variables. */
|
151
|
+
/*=========================================================*/
|
152
|
+
|
153
|
+
if (patternPtr->pnType == PATTERN_CE_NODE)
|
154
|
+
{
|
155
|
+
/*====================================================*/
|
156
|
+
/* Determine if the fact address associated with this */
|
157
|
+
/* pattern illegally refers to other variables. */
|
158
|
+
/*====================================================*/
|
159
|
+
|
160
|
+
if ((patternPtr->value != NULL) &&
|
161
|
+
(patternPtr->referringNode != NULL))
|
162
|
+
{
|
163
|
+
errorFlag = true;
|
164
|
+
if (patternPtr->referringNode->index == NO_INDEX)
|
165
|
+
{
|
166
|
+
PrintErrorID(theEnv,"ANALYSIS",1,true);
|
167
|
+
WriteString(theEnv,STDERR,"Duplicate pattern-address ?");
|
168
|
+
WriteString(theEnv,STDERR,patternPtr->lexemeValue->contents);
|
169
|
+
WriteString(theEnv,STDERR," found in CE #");
|
170
|
+
WriteInteger(theEnv,STDERR,patternPtr->whichCE);
|
171
|
+
WriteString(theEnv,STDERR,".\n");
|
172
|
+
}
|
173
|
+
else
|
174
|
+
{
|
175
|
+
PrintErrorID(theEnv,"ANALYSIS",2,true);
|
176
|
+
WriteString(theEnv,STDERR,"Pattern-address ?");
|
177
|
+
WriteString(theEnv,STDERR,patternPtr->lexemeValue->contents);
|
178
|
+
WriteString(theEnv,STDERR," used in CE #");
|
179
|
+
WriteInteger(theEnv,STDERR,patternPtr->whichCE);
|
180
|
+
WriteString(theEnv,STDERR," was previously bound within a pattern CE.\n");
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
/*====================================================*/
|
185
|
+
/* Propagate the pattern and field location of bound */
|
186
|
+
/* variables found in this pattern to other variables */
|
187
|
+
/* in the same semantic scope as the bound variable. */
|
188
|
+
/*====================================================*/
|
189
|
+
|
190
|
+
if (GetVariables(theEnv,patternPtr,PATTERN_CE_NODE,theNandFrames))
|
191
|
+
{
|
192
|
+
ReleaseNandFrames(theEnv,theNandFrames);
|
193
|
+
return true;
|
194
|
+
}
|
195
|
+
|
196
|
+
/*==========================================================*/
|
197
|
+
/* Analyze any test CE that's been attached to the pattern. */
|
198
|
+
/*==========================================================*/
|
199
|
+
|
200
|
+
if (TestCEAnalysis(theEnv,patternPtr,patternPtr->expression,false,&errorFlag,theNandFrames) == true)
|
201
|
+
{
|
202
|
+
ReleaseNandFrames(theEnv,theNandFrames);
|
203
|
+
return true;
|
204
|
+
}
|
205
|
+
|
206
|
+
if (TestCEAnalysis(theEnv,patternPtr,patternPtr->secondaryExpression,true,&errorFlag,theNandFrames) == true)
|
207
|
+
{
|
208
|
+
ReleaseNandFrames(theEnv,theNandFrames);
|
209
|
+
return true;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
/*==============================================================*/
|
214
|
+
/* If a test CE is encountered, make sure that all references */
|
215
|
+
/* to variables have been previously bound. If they are bound */
|
216
|
+
/* then replace the references to variables with function calls */
|
217
|
+
/* to retrieve the variables. */
|
218
|
+
/*==============================================================*/
|
219
|
+
|
220
|
+
else if (patternPtr->pnType == TEST_CE_NODE)
|
221
|
+
{
|
222
|
+
if (TestCEAnalysis(theEnv,patternPtr,patternPtr->expression,false,&errorFlag,theNandFrames) == true)
|
223
|
+
{
|
224
|
+
ReleaseNandFrames(theEnv,theNandFrames);
|
225
|
+
return true;
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
/*==================================*/
|
230
|
+
/* If the nand depth is decreasing, */
|
231
|
+
/* release the nand frames. */
|
232
|
+
/*==================================*/
|
233
|
+
|
234
|
+
while (patternPtr->endNandDepth < currentDepth)
|
235
|
+
{
|
236
|
+
tempNandPtr = theNandFrames->next;
|
237
|
+
rtn_struct(theEnv,nandFrame,theNandFrames);
|
238
|
+
theNandFrames = tempNandPtr;
|
239
|
+
currentDepth--;
|
240
|
+
}
|
241
|
+
|
242
|
+
/*=====================================================*/
|
243
|
+
/* Move on to the next pattern in the LHS of the rule. */
|
244
|
+
/*=====================================================*/
|
245
|
+
|
246
|
+
patternPtr = patternPtr->bottom;
|
247
|
+
}
|
248
|
+
|
249
|
+
/*==========================================*/
|
250
|
+
/* Return the error status of the analysis. */
|
251
|
+
/*==========================================*/
|
252
|
+
|
253
|
+
return(errorFlag);
|
254
|
+
}
|
255
|
+
|
256
|
+
/******************************************************/
|
257
|
+
/* ReleaseNandFrames: Releases a list of nand frames. */
|
258
|
+
/******************************************************/
|
259
|
+
static void ReleaseNandFrames(
|
260
|
+
Environment *theEnv,
|
261
|
+
struct nandFrame *theFrames)
|
262
|
+
{
|
263
|
+
struct nandFrame *tmpFrame;
|
264
|
+
|
265
|
+
while (theFrames != NULL)
|
266
|
+
{
|
267
|
+
tmpFrame = theFrames->next;
|
268
|
+
rtn_struct(theEnv,nandFrame,theFrames);
|
269
|
+
theFrames = tmpFrame;
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
/*******************************************************************/
|
274
|
+
/* TestCEAnalysis: If a test CE is encountered, make sure that all */
|
275
|
+
/* references to variables have been previously bound. If they */
|
276
|
+
/* are bound then replace the references to variables with */
|
277
|
+
/* function calls to retrieve the variables. */
|
278
|
+
/*******************************************************************/
|
279
|
+
static bool TestCEAnalysis(
|
280
|
+
Environment *theEnv,
|
281
|
+
struct lhsParseNode *patternPtr,
|
282
|
+
struct lhsParseNode *theExpression,
|
283
|
+
bool secondary,
|
284
|
+
bool *errorFlag,
|
285
|
+
struct nandFrame *theNandFrames)
|
286
|
+
{
|
287
|
+
struct lhsParseNode *rv, *theList, *tempList, *tempRight;
|
288
|
+
|
289
|
+
if (theExpression == NULL) return false;
|
290
|
+
|
291
|
+
/*=====================================================*/
|
292
|
+
/* Verify that all variables were referenced properly. */
|
293
|
+
/*=====================================================*/
|
294
|
+
|
295
|
+
rv = CheckExpression(theEnv,theExpression,NULL,patternPtr->whichCE,NULL,0);
|
296
|
+
|
297
|
+
/*====================================================================*/
|
298
|
+
/* Temporarily disconnect the right nodes. If this is a pattern node */
|
299
|
+
/* with an attached test CE, we only want to propagate to following */
|
300
|
+
/* patterns, not to nodes of this pattern which preceded the test CE. */
|
301
|
+
/*====================================================================*/
|
302
|
+
|
303
|
+
tempRight = patternPtr->right;
|
304
|
+
patternPtr->right = NULL;
|
305
|
+
|
306
|
+
/*=========================================================*/
|
307
|
+
/* Determine the type and value constraints implied by the */
|
308
|
+
/* expression and propagate these constraints to other */
|
309
|
+
/* variables in the LHS. For example, the expression */
|
310
|
+
/* (+ ?x 1) implies that ?x is a number. */
|
311
|
+
/*=========================================================*/
|
312
|
+
|
313
|
+
theList = GetExpressionVarConstraints(theEnv,theExpression);
|
314
|
+
for (tempList = theList; tempList != NULL; tempList = tempList->right)
|
315
|
+
{
|
316
|
+
if (PropagateVariableDriver(theEnv,patternPtr,patternPtr,NULL,SF_VARIABLE_NODE,
|
317
|
+
tempList->lexemeValue,tempList,false,TEST_CE_NODE))
|
318
|
+
{
|
319
|
+
ReturnLHSParseNodes(theEnv,theList);
|
320
|
+
patternPtr->right = tempRight;
|
321
|
+
return true;
|
322
|
+
}
|
323
|
+
}
|
324
|
+
|
325
|
+
ReturnLHSParseNodes(theEnv,theList);
|
326
|
+
|
327
|
+
/*============================*/
|
328
|
+
/* Reconnect the right nodes. */
|
329
|
+
/*============================*/
|
330
|
+
|
331
|
+
patternPtr->right = tempRight;
|
332
|
+
|
333
|
+
/*========================================================*/
|
334
|
+
/* If the variables in the expression were all referenced */
|
335
|
+
/* properly, then create the expression to use in the */
|
336
|
+
/* join network. */
|
337
|
+
/*========================================================*/
|
338
|
+
|
339
|
+
if (rv != NULL)
|
340
|
+
{ *errorFlag = true; }
|
341
|
+
else if (secondary)
|
342
|
+
{ patternPtr->secondaryNetworkTest = CombineExpressions(theEnv,patternPtr->secondaryNetworkTest,GetvarReplace(theEnv,theExpression,false,theNandFrames)); }
|
343
|
+
else
|
344
|
+
{ patternPtr->networkTest = CombineExpressions(theEnv,patternPtr->networkTest,GetvarReplace(theEnv,theExpression,false,theNandFrames)); }
|
345
|
+
|
346
|
+
return false;
|
347
|
+
}
|
348
|
+
|
349
|
+
/****************************************************************/
|
350
|
+
/* GetVariables: Loops through each field/slot within a pattern */
|
351
|
+
/* and propagates the pattern and field location of bound */
|
352
|
+
/* variables found in the pattern to other variables within */
|
353
|
+
/* the same semantic scope as the bound variables. */
|
354
|
+
/****************************************************************/
|
355
|
+
static bool GetVariables(
|
356
|
+
Environment *theEnv,
|
357
|
+
struct lhsParseNode *thePattern,
|
358
|
+
ParseNodeType patternHeadType,
|
359
|
+
struct nandFrame *theNandFrames)
|
360
|
+
{
|
361
|
+
struct lhsParseNode *patternHead = thePattern;
|
362
|
+
struct lhsParseNode *multifieldHeader = NULL;
|
363
|
+
|
364
|
+
/*======================================================*/
|
365
|
+
/* Loop through all the fields/slots found in a pattern */
|
366
|
+
/* looking for binding instances of variables. */
|
367
|
+
/*======================================================*/
|
368
|
+
|
369
|
+
while (thePattern != NULL)
|
370
|
+
{
|
371
|
+
/*================================================*/
|
372
|
+
/* A multifield slot contains a sublist of fields */
|
373
|
+
/* that must be traversed and checked. */
|
374
|
+
/*================================================*/
|
375
|
+
|
376
|
+
if (thePattern->multifieldSlot)
|
377
|
+
{
|
378
|
+
multifieldHeader = thePattern;
|
379
|
+
thePattern = thePattern->bottom;
|
380
|
+
}
|
381
|
+
|
382
|
+
/*==================================================*/
|
383
|
+
/* Propagate the binding occurences of single field */
|
384
|
+
/* variables, multifield variables, and fact */
|
385
|
+
/* addresses to other occurences of the variable. */
|
386
|
+
/* If an error is encountered, return true. */
|
387
|
+
/*==================================================*/
|
388
|
+
|
389
|
+
if (thePattern != NULL)
|
390
|
+
{
|
391
|
+
if ((thePattern->pnType == SF_VARIABLE_NODE) ||
|
392
|
+
(thePattern->pnType == MF_VARIABLE_NODE) ||
|
393
|
+
((thePattern->pnType == PATTERN_CE_NODE) && (thePattern->value != NULL)))
|
394
|
+
{
|
395
|
+
if (ProcessVariable(theEnv,thePattern,multifieldHeader,patternHead,patternHeadType,theNandFrames))
|
396
|
+
{ return true; }
|
397
|
+
}
|
398
|
+
else
|
399
|
+
{
|
400
|
+
if (ProcessField(theEnv,thePattern,multifieldHeader,patternHead,patternHeadType,theNandFrames))
|
401
|
+
{ return true; }
|
402
|
+
}
|
403
|
+
}
|
404
|
+
|
405
|
+
/*===============================================*/
|
406
|
+
/* Move on to the next field/slot in the pattern */
|
407
|
+
/* or to the next field in a multifield slot. */
|
408
|
+
/*===============================================*/
|
409
|
+
|
410
|
+
if (thePattern == NULL)
|
411
|
+
{
|
412
|
+
thePattern = multifieldHeader;
|
413
|
+
multifieldHeader = NULL;
|
414
|
+
}
|
415
|
+
else if ((thePattern->right == NULL) && (multifieldHeader != NULL))
|
416
|
+
{
|
417
|
+
thePattern = multifieldHeader;
|
418
|
+
multifieldHeader = NULL;
|
419
|
+
}
|
420
|
+
|
421
|
+
thePattern = thePattern->right;
|
422
|
+
}
|
423
|
+
|
424
|
+
/*===============================*/
|
425
|
+
/* Return false to indicate that */
|
426
|
+
/* no errors were detected. */
|
427
|
+
/*===============================*/
|
428
|
+
|
429
|
+
return false;
|
430
|
+
}
|
431
|
+
|
432
|
+
/******************************************************/
|
433
|
+
/* ProcessVariable: Processes a single occurence of a */
|
434
|
+
/* variable by propagating references to it. */
|
435
|
+
/******************************************************/
|
436
|
+
static bool ProcessVariable(
|
437
|
+
Environment *theEnv,
|
438
|
+
struct lhsParseNode *thePattern,
|
439
|
+
struct lhsParseNode *multifieldHeader,
|
440
|
+
struct lhsParseNode *patternHead,
|
441
|
+
ParseNodeType patternHeadType,
|
442
|
+
struct nandFrame *theNandFrames)
|
443
|
+
{
|
444
|
+
ParseNodeType theType;
|
445
|
+
CLIPSLexeme *theVariable;
|
446
|
+
struct constraintRecord *theConstraints;
|
447
|
+
|
448
|
+
/*=============================================================*/
|
449
|
+
/* If a pattern address is being propagated, then treat it as */
|
450
|
+
/* a single field pattern variable and create a constraint */
|
451
|
+
/* which indicates that is must be a fact or instance address. */
|
452
|
+
/* This code will have to be modified for new data types which */
|
453
|
+
/* can match patterns. */
|
454
|
+
/*=============================================================*/
|
455
|
+
|
456
|
+
if (thePattern->pnType == PATTERN_CE_NODE)
|
457
|
+
{
|
458
|
+
theType = SF_VARIABLE_NODE;
|
459
|
+
theVariable = (CLIPSLexeme *) thePattern->value;
|
460
|
+
if (thePattern->derivedConstraints) RemoveConstraint(theEnv,thePattern->constraints);
|
461
|
+
theConstraints = GetConstraintRecord(theEnv);
|
462
|
+
thePattern->constraints = theConstraints;
|
463
|
+
thePattern->constraints->anyAllowed = false;
|
464
|
+
thePattern->constraints->instanceAddressesAllowed = true;
|
465
|
+
thePattern->constraints->factAddressesAllowed = true;
|
466
|
+
thePattern->derivedConstraints = true;
|
467
|
+
}
|
468
|
+
|
469
|
+
/*===================================================*/
|
470
|
+
/* Otherwise a pattern variable is being propagated. */
|
471
|
+
/*===================================================*/
|
472
|
+
|
473
|
+
else
|
474
|
+
{
|
475
|
+
theType = thePattern->pnType;
|
476
|
+
theVariable = (CLIPSLexeme *) thePattern->value;
|
477
|
+
}
|
478
|
+
|
479
|
+
/*===================================================*/
|
480
|
+
/* Propagate the variable location to any additional */
|
481
|
+
/* fields associated with the binding variable. */
|
482
|
+
/*===================================================*/
|
483
|
+
|
484
|
+
if (thePattern->pnType != PATTERN_CE_NODE)
|
485
|
+
{
|
486
|
+
PropagateVariableToNodes(theEnv,thePattern->bottom,theType,theVariable,
|
487
|
+
thePattern,patternHead->beginNandDepth,
|
488
|
+
true,false);
|
489
|
+
|
490
|
+
if (ProcessField(theEnv,thePattern,multifieldHeader,patternHead,patternHeadType,theNandFrames))
|
491
|
+
{ return true; }
|
492
|
+
}
|
493
|
+
|
494
|
+
/*=================================================================*/
|
495
|
+
/* Propagate the constraints to other fields, slots, and patterns. */
|
496
|
+
/*=================================================================*/
|
497
|
+
|
498
|
+
return(PropagateVariableDriver(theEnv,patternHead,thePattern,multifieldHeader,theType,
|
499
|
+
theVariable,thePattern,true,patternHeadType));
|
500
|
+
}
|
501
|
+
|
502
|
+
/*******************************************/
|
503
|
+
/* PropagateVariableDriver: Driver routine */
|
504
|
+
/* for propagating variable references. */
|
505
|
+
/*******************************************/
|
506
|
+
static bool PropagateVariableDriver(
|
507
|
+
Environment *theEnv,
|
508
|
+
struct lhsParseNode *patternHead,
|
509
|
+
struct lhsParseNode *theNode,
|
510
|
+
struct lhsParseNode *multifieldHeader,
|
511
|
+
ParseNodeType theType,
|
512
|
+
CLIPSLexeme *variableName,
|
513
|
+
struct lhsParseNode *theReference,
|
514
|
+
bool assignReference,
|
515
|
+
ParseNodeType patternHeadType)
|
516
|
+
{
|
517
|
+
/*===================================================*/
|
518
|
+
/* Propagate the variable location to any additional */
|
519
|
+
/* constraints associated with the binding variable. */
|
520
|
+
/*===================================================*/
|
521
|
+
|
522
|
+
if (multifieldHeader != NULL)
|
523
|
+
{
|
524
|
+
if (PropagateVariableToNodes(theEnv,multifieldHeader->right,theType,variableName,
|
525
|
+
theReference,patternHead->beginNandDepth,assignReference,false))
|
526
|
+
{
|
527
|
+
VariableMixingErrorMessage(theEnv,variableName);
|
528
|
+
return true;
|
529
|
+
}
|
530
|
+
}
|
531
|
+
|
532
|
+
/*========================================================*/
|
533
|
+
/* Propagate the variable location to fields/slots in the */
|
534
|
+
/* same pattern which appear after the binding variable. */
|
535
|
+
/*========================================================*/
|
536
|
+
|
537
|
+
if (PropagateVariableToNodes(theEnv,theNode->right,theType,variableName,theReference,
|
538
|
+
patternHead->beginNandDepth,assignReference,false))
|
539
|
+
{
|
540
|
+
VariableMixingErrorMessage(theEnv,variableName);
|
541
|
+
return true;
|
542
|
+
}
|
543
|
+
|
544
|
+
/*==============================================*/
|
545
|
+
/* Propagate the variable location to any test */
|
546
|
+
/* CEs which have been attached to the pattern. */
|
547
|
+
/*==============================================*/
|
548
|
+
|
549
|
+
if (PropagateVariableToNodes(theEnv,patternHead->expression,theType,variableName,theReference,
|
550
|
+
patternHead->beginNandDepth,assignReference,true))
|
551
|
+
{ return true; }
|
552
|
+
|
553
|
+
if (PropagateVariableToNodes(theEnv,patternHead->secondaryExpression,theType,variableName,theReference,
|
554
|
+
patternHead->beginNandDepth,assignReference,true))
|
555
|
+
{ return true; }
|
556
|
+
|
557
|
+
/*======================================================*/
|
558
|
+
/* Propagate values to other patterns if the pattern in */
|
559
|
+
/* which the variable is found is not a "not" CE or the */
|
560
|
+
/* last pattern within a nand CE. */
|
561
|
+
/*======================================================*/
|
562
|
+
|
563
|
+
if (((patternHead->pnType == PATTERN_CE_NODE) || (patternHead->pnType == TEST_CE_NODE)) &&
|
564
|
+
(patternHead->negated == false) &&
|
565
|
+
(patternHead->exists == false) &&
|
566
|
+
(patternHead->beginNandDepth <= patternHead->endNandDepth))
|
567
|
+
{
|
568
|
+
bool ignoreVariableMixing;
|
569
|
+
|
570
|
+
/*============================================================*/
|
571
|
+
/* If the variables are propagated from a test CE, then don't */
|
572
|
+
/* check for mixing of single and multifield variables (since */
|
573
|
+
/* previously bound multifield variables typically have the $ */
|
574
|
+
/* removed when passed as an argument to a function unless */
|
575
|
+
/* sequence expansion is desired). */
|
576
|
+
/*============================================================*/
|
577
|
+
|
578
|
+
if (patternHeadType == TEST_CE_NODE) ignoreVariableMixing = true;
|
579
|
+
else ignoreVariableMixing = false;
|
580
|
+
|
581
|
+
/*==========================*/
|
582
|
+
/* Propagate the reference. */
|
583
|
+
/*==========================*/
|
584
|
+
|
585
|
+
if (PropagateVariableToNodes(theEnv,patternHead->bottom,theType,variableName,theReference,
|
586
|
+
patternHead->beginNandDepth,assignReference,
|
587
|
+
ignoreVariableMixing))
|
588
|
+
{
|
589
|
+
VariableMixingErrorMessage(theEnv,variableName);
|
590
|
+
return true;
|
591
|
+
}
|
592
|
+
}
|
593
|
+
|
594
|
+
/*==============================================*/
|
595
|
+
/* Return false to indicate that no errors were */
|
596
|
+
/* generated by the variable propagation. */
|
597
|
+
/*==============================================*/
|
598
|
+
|
599
|
+
return false;
|
600
|
+
}
|
601
|
+
|
602
|
+
/********************************************************/
|
603
|
+
/* ProcessField: Processes a field or slot of a pattern */
|
604
|
+
/* which does not contain a binding variable. */
|
605
|
+
/********************************************************/
|
606
|
+
static bool ProcessField(
|
607
|
+
Environment *theEnv,
|
608
|
+
struct lhsParseNode *thePattern,
|
609
|
+
struct lhsParseNode *multifieldHeader,
|
610
|
+
struct lhsParseNode *patternHead,
|
611
|
+
ParseNodeType patternHeadType,
|
612
|
+
struct nandFrame *theNandFrames)
|
613
|
+
{
|
614
|
+
struct lhsParseNode *theList, *tempList;
|
615
|
+
|
616
|
+
/*====================================================*/
|
617
|
+
/* Nothing needs to be done for the node representing */
|
618
|
+
/* the entire pattern. Return false to indicate that */
|
619
|
+
/* no errors were generated. */
|
620
|
+
/*====================================================*/
|
621
|
+
|
622
|
+
if (thePattern->pnType == PATTERN_CE_NODE) return false;
|
623
|
+
|
624
|
+
/*====================================================================*/
|
625
|
+
/* Derive a set of constraints based on values found in the slot or */
|
626
|
+
/* field. For example, if a slot can only contain the values 1, 2, or */
|
627
|
+
/* 3, the field constraint ~2 would generate a constraint record that */
|
628
|
+
/* only allows the value 1 or 3. Once generated, the constraints are */
|
629
|
+
/* propagated to other slots and fields. */
|
630
|
+
/*====================================================================*/
|
631
|
+
|
632
|
+
theList = DeriveVariableConstraints(theEnv,thePattern);
|
633
|
+
for (tempList = theList; tempList != NULL; tempList = tempList->right)
|
634
|
+
{
|
635
|
+
if (PropagateVariableDriver(theEnv,patternHead,thePattern,multifieldHeader,tempList->pnType,
|
636
|
+
tempList->lexemeValue,tempList,false,patternHeadType))
|
637
|
+
{
|
638
|
+
ReturnLHSParseNodes(theEnv,theList);
|
639
|
+
return true;
|
640
|
+
}
|
641
|
+
}
|
642
|
+
ReturnLHSParseNodes(theEnv,theList);
|
643
|
+
|
644
|
+
/*===========================================================*/
|
645
|
+
/* Check for "variable referenced, but not previously bound" */
|
646
|
+
/* errors. Return true if this type of error is detected. */
|
647
|
+
/*===========================================================*/
|
648
|
+
|
649
|
+
if (UnboundVariablesInPattern(theEnv,thePattern,patternHead->whichCE))
|
650
|
+
{ return true; }
|
651
|
+
|
652
|
+
/*==================================================*/
|
653
|
+
/* Check for constraint errors for this slot/field. */
|
654
|
+
/* If the slot/field has unmatchable constraints */
|
655
|
+
/* then return true to indicate a semantic error. */
|
656
|
+
/*==================================================*/
|
657
|
+
|
658
|
+
if (ProcessConnectedConstraints(theEnv,thePattern,multifieldHeader,patternHead))
|
659
|
+
{ return true; }
|
660
|
+
|
661
|
+
/*==============================================================*/
|
662
|
+
/* Convert the slot/field constraint to a series of expressions */
|
663
|
+
/* that will be used in the pattern and join networks. */
|
664
|
+
/*==============================================================*/
|
665
|
+
|
666
|
+
FieldConversion(theEnv,thePattern,patternHead,theNandFrames);
|
667
|
+
|
668
|
+
/*=========================================================*/
|
669
|
+
/* Return false to indicate that no errors were generated. */
|
670
|
+
/*=========================================================*/
|
671
|
+
|
672
|
+
return false;
|
673
|
+
}
|
674
|
+
|
675
|
+
/*************************************************************/
|
676
|
+
/* PropagateVariableToNodes: Propagates variable references */
|
677
|
+
/* to all other variables within the semantic scope of the */
|
678
|
+
/* bound variable. That is, a variable reference cannot be */
|
679
|
+
/* beyond an enclosing not/and CE combination. The */
|
680
|
+
/* restriction of propagating variables beyond an enclosing */
|
681
|
+
/* not CE is handled within the GetVariables function. */
|
682
|
+
/*************************************************************/
|
683
|
+
static bool PropagateVariableToNodes(
|
684
|
+
Environment *theEnv,
|
685
|
+
struct lhsParseNode *theNode,
|
686
|
+
ParseNodeType theType,
|
687
|
+
CLIPSLexeme *variableName,
|
688
|
+
struct lhsParseNode *theReference,
|
689
|
+
int startDepth,
|
690
|
+
bool assignReference,
|
691
|
+
bool ignoreVariableTypes)
|
692
|
+
{
|
693
|
+
struct constraintRecord *tempConstraints;
|
694
|
+
|
695
|
+
/*===========================================*/
|
696
|
+
/* Traverse the nodes using the bottom link. */
|
697
|
+
/*===========================================*/
|
698
|
+
|
699
|
+
while (theNode != NULL)
|
700
|
+
{
|
701
|
+
/*==================================================*/
|
702
|
+
/* If the field/slot contains a predicate or return */
|
703
|
+
/* value constraint, then propagate the variable to */
|
704
|
+
/* the expression associated with that constraint. */
|
705
|
+
/*==================================================*/
|
706
|
+
|
707
|
+
if (theNode->expression != NULL)
|
708
|
+
{
|
709
|
+
PropagateVariableToNodes(theEnv,theNode->expression,theType,variableName,
|
710
|
+
theReference,startDepth,assignReference,true);
|
711
|
+
}
|
712
|
+
|
713
|
+
if (theNode->secondaryExpression != NULL)
|
714
|
+
{
|
715
|
+
PropagateVariableToNodes(theEnv,theNode->secondaryExpression,theType,variableName,
|
716
|
+
theReference,startDepth,assignReference,true);
|
717
|
+
}
|
718
|
+
|
719
|
+
/*======================================================*/
|
720
|
+
/* If the field/slot is a single or multifield variable */
|
721
|
+
/* with the same name as the propagated variable, */
|
722
|
+
/* then propagate the variable location to this node. */
|
723
|
+
/*======================================================*/
|
724
|
+
|
725
|
+
else if (((theNode->pnType == SF_VARIABLE_NODE) || (theNode->pnType == MF_VARIABLE_NODE)) &&
|
726
|
+
(theNode->value == (void *) variableName))
|
727
|
+
{
|
728
|
+
/*======================================================*/
|
729
|
+
/* Check for mixing of single and multifield variables. */
|
730
|
+
/*======================================================*/
|
731
|
+
|
732
|
+
if (ignoreVariableTypes == false)
|
733
|
+
{
|
734
|
+
if (((theType == SF_VARIABLE_NODE) && (theNode->pnType == MF_VARIABLE_NODE)) ||
|
735
|
+
((theType == MF_VARIABLE_NODE) && (theNode->pnType == SF_VARIABLE_NODE)))
|
736
|
+
{ return true; }
|
737
|
+
}
|
738
|
+
|
739
|
+
/*======================================================*/
|
740
|
+
/* Intersect the propagated variable's constraints with */
|
741
|
+
/* the current constraints for this field/slot. */
|
742
|
+
/*======================================================*/
|
743
|
+
|
744
|
+
if ((theReference->constraints != NULL) && (! theNode->negated))
|
745
|
+
{
|
746
|
+
tempConstraints = theNode->constraints;
|
747
|
+
theNode->constraints = IntersectConstraints(theEnv,theReference->constraints,
|
748
|
+
tempConstraints);
|
749
|
+
if (theNode->derivedConstraints)
|
750
|
+
{ RemoveConstraint(theEnv,tempConstraints); }
|
751
|
+
|
752
|
+
theNode->derivedConstraints = true;
|
753
|
+
}
|
754
|
+
|
755
|
+
/*=====================================================*/
|
756
|
+
/* Don't propagate the variable if it originates from */
|
757
|
+
/* a different type of pattern object and the variable */
|
758
|
+
/* reference has already been resolved. */
|
759
|
+
/*=====================================================*/
|
760
|
+
|
761
|
+
if (assignReference)
|
762
|
+
{
|
763
|
+
if (theNode->referringNode == NULL)
|
764
|
+
{ theNode->referringNode = theReference; }
|
765
|
+
else if (theReference->pattern == theNode->pattern)
|
766
|
+
{ theNode->referringNode = theReference; }
|
767
|
+
else if (theReference->patternType == theNode->patternType)
|
768
|
+
{ theNode->referringNode = theReference; }
|
769
|
+
}
|
770
|
+
}
|
771
|
+
|
772
|
+
/*========================================================*/
|
773
|
+
/* If the field/slot is the node representing the entire */
|
774
|
+
/* pattern, then propagate the variable location to the */
|
775
|
+
/* fact address associated with the pattern (if it is the */
|
776
|
+
/* same variable name). */
|
777
|
+
/*========================================================*/
|
778
|
+
|
779
|
+
else if ((theNode->pnType == PATTERN_CE_NODE) &&
|
780
|
+
(theNode->value == (void *) variableName) &&
|
781
|
+
(assignReference == true))
|
782
|
+
{
|
783
|
+
if (theType == MF_VARIABLE) return true;
|
784
|
+
|
785
|
+
theNode->referringNode = theReference;
|
786
|
+
}
|
787
|
+
|
788
|
+
/*=====================================================*/
|
789
|
+
/* Propagate the variable to other fields contained */
|
790
|
+
/* within the same & field constraint or same pattern. */
|
791
|
+
/*=====================================================*/
|
792
|
+
|
793
|
+
if (theNode->right != NULL)
|
794
|
+
{
|
795
|
+
if (PropagateVariableToNodes(theEnv,theNode->right,theType,variableName,
|
796
|
+
theReference,startDepth,assignReference,ignoreVariableTypes))
|
797
|
+
{ return true; }
|
798
|
+
}
|
799
|
+
|
800
|
+
/*============================================================*/
|
801
|
+
/* Propagate the variable to other patterns within the same */
|
802
|
+
/* semantic scope (if dealing with the node for an entire */
|
803
|
+
/* pattern) or to the next | field constraint within a field. */
|
804
|
+
/*============================================================*/
|
805
|
+
|
806
|
+
if ((theNode->pnType == PATTERN_CE_NODE) || (theNode->pnType == TEST_CE_NODE))
|
807
|
+
{
|
808
|
+
if (theNode->endNandDepth < startDepth) theNode = NULL;
|
809
|
+
else theNode = theNode->bottom;
|
810
|
+
}
|
811
|
+
else
|
812
|
+
{ theNode = theNode->bottom; }
|
813
|
+
}
|
814
|
+
|
815
|
+
/*========================================================*/
|
816
|
+
/* Return false to indicate that no errors were detected. */
|
817
|
+
/*========================================================*/
|
818
|
+
|
819
|
+
return false;
|
820
|
+
}
|
821
|
+
|
822
|
+
/*************************************************************/
|
823
|
+
/* UnboundVariablesInPattern: Verifies that variables within */
|
824
|
+
/* a slot/field have been referenced properly (i.e. that */
|
825
|
+
/* variables have been previously bound if they are not a */
|
826
|
+
/* binding occurrence). */
|
827
|
+
/*************************************************************/
|
828
|
+
static bool UnboundVariablesInPattern(
|
829
|
+
Environment *theEnv,
|
830
|
+
struct lhsParseNode *theSlot,
|
831
|
+
unsigned short pattern)
|
832
|
+
{
|
833
|
+
struct lhsParseNode *andField;
|
834
|
+
struct lhsParseNode *rv;
|
835
|
+
ConstraintViolationType result;
|
836
|
+
struct lhsParseNode *orField;
|
837
|
+
CLIPSLexeme *slotName;
|
838
|
+
CONSTRAINT_RECORD *theConstraints;
|
839
|
+
unsigned short theField;
|
840
|
+
|
841
|
+
/*===================================================*/
|
842
|
+
/* If a multifield slot is being checked, then check */
|
843
|
+
/* each of the fields grouped with the multifield. */
|
844
|
+
/*===================================================*/
|
845
|
+
|
846
|
+
if (theSlot->multifieldSlot)
|
847
|
+
{
|
848
|
+
theSlot = theSlot->bottom;
|
849
|
+
while (theSlot != NULL)
|
850
|
+
{
|
851
|
+
if (UnboundVariablesInPattern(theEnv,theSlot,pattern))
|
852
|
+
{ return true; }
|
853
|
+
theSlot = theSlot->right;
|
854
|
+
}
|
855
|
+
|
856
|
+
return false;
|
857
|
+
}
|
858
|
+
|
859
|
+
/*=======================*/
|
860
|
+
/* Check a single field. */
|
861
|
+
/*=======================*/
|
862
|
+
|
863
|
+
slotName = theSlot->slot;
|
864
|
+
theField = theSlot->index;
|
865
|
+
theConstraints = theSlot->constraints;
|
866
|
+
|
867
|
+
/*===========================================*/
|
868
|
+
/* Loop through each of the '|' constraints. */
|
869
|
+
/*===========================================*/
|
870
|
+
|
871
|
+
for (orField = theSlot->bottom;
|
872
|
+
orField != NULL;
|
873
|
+
orField = orField->bottom)
|
874
|
+
{
|
875
|
+
/*===========================================*/
|
876
|
+
/* Loop through each of the fields connected */
|
877
|
+
/* by the '&' within the '|' constraint. */
|
878
|
+
/*===========================================*/
|
879
|
+
|
880
|
+
for (andField = orField;
|
881
|
+
andField != NULL;
|
882
|
+
andField = andField->right)
|
883
|
+
{
|
884
|
+
/*=======================================================*/
|
885
|
+
/* If this is not a binding occurence of a variable and */
|
886
|
+
/* there is no previous binding occurence of a variable, */
|
887
|
+
/* then generate an error message for a variable that is */
|
888
|
+
/* referred to but not bound. */
|
889
|
+
/*=======================================================*/
|
890
|
+
|
891
|
+
if (((andField->pnType == SF_VARIABLE_NODE) || (andField->pnType == MF_VARIABLE_NODE)) &&
|
892
|
+
(andField->referringNode == NULL))
|
893
|
+
{
|
894
|
+
VariableReferenceErrorMessage(theEnv,andField->lexemeValue,NULL,pattern,
|
895
|
+
slotName,theField);
|
896
|
+
return true;
|
897
|
+
}
|
898
|
+
|
899
|
+
/*==============================================*/
|
900
|
+
/* Check predicate and return value constraints */
|
901
|
+
/* to insure that all variables used within the */
|
902
|
+
/* constraint have been previously bound. */
|
903
|
+
/*==============================================*/
|
904
|
+
|
905
|
+
else if ((andField->pnType == PREDICATE_CONSTRAINT_NODE) ||
|
906
|
+
(andField->pnType == RETURN_VALUE_CONSTRAINT_NODE))
|
907
|
+
{
|
908
|
+
rv = CheckExpression(theEnv,andField->expression,NULL,pattern,slotName,theField);
|
909
|
+
if (rv != NULL) return true;
|
910
|
+
}
|
911
|
+
|
912
|
+
/*========================================================*/
|
913
|
+
/* If static constraint checking is being performed, then */
|
914
|
+
/* determine if constant values have violated the set of */
|
915
|
+
/* derived constraints for the slot/field (based on the */
|
916
|
+
/* deftemplate definition and propagated constraints). */
|
917
|
+
/*========================================================*/
|
918
|
+
|
919
|
+
else if (((andField->pnType == INTEGER_NODE) || (andField->pnType == FLOAT_NODE) ||
|
920
|
+
(andField->pnType == SYMBOL_NODE) || (andField->pnType == STRING_NODE) ||
|
921
|
+
(andField->pnType == INSTANCE_NAME_NODE)))
|
922
|
+
{
|
923
|
+
result = ConstraintCheckValue(theEnv,NodeTypeToType(andField),andField->value,theConstraints);
|
924
|
+
if (result != NO_VIOLATION)
|
925
|
+
{
|
926
|
+
ConstraintViolationErrorMessage(theEnv,"A literal restriction value",
|
927
|
+
NULL,false,pattern,
|
928
|
+
slotName,theField,result,
|
929
|
+
theConstraints,true);
|
930
|
+
return true;
|
931
|
+
}
|
932
|
+
}
|
933
|
+
}
|
934
|
+
}
|
935
|
+
|
936
|
+
/*===============================*/
|
937
|
+
/* Return false to indicate that */
|
938
|
+
/* no errors were detected. */
|
939
|
+
/*===============================*/
|
940
|
+
|
941
|
+
return false;
|
942
|
+
}
|
943
|
+
|
944
|
+
/******************************************************************/
|
945
|
+
/* CheckExpression: Verifies that variables within an expression */
|
946
|
+
/* have been referenced properly. All variables within an */
|
947
|
+
/* expression must have been previously bound. */
|
948
|
+
/******************************************************************/
|
949
|
+
static struct lhsParseNode *CheckExpression(
|
950
|
+
Environment *theEnv,
|
951
|
+
struct lhsParseNode *exprPtr,
|
952
|
+
struct lhsParseNode *lastOne,
|
953
|
+
unsigned short whichCE,
|
954
|
+
CLIPSLexeme *slotName,
|
955
|
+
unsigned short theField)
|
956
|
+
{
|
957
|
+
struct lhsParseNode *rv;
|
958
|
+
unsigned short i = 1;
|
959
|
+
|
960
|
+
while (exprPtr != NULL)
|
961
|
+
{
|
962
|
+
/*===============================================================*/
|
963
|
+
/* Check that single field variables contained in the expression */
|
964
|
+
/* were previously defined in the LHS. Also check to see if the */
|
965
|
+
/* variable has unmatchable constraints. */
|
966
|
+
/*===============================================================*/
|
967
|
+
|
968
|
+
if (exprPtr->pnType == SF_VARIABLE_NODE)
|
969
|
+
{
|
970
|
+
if (exprPtr->referringNode == NULL)
|
971
|
+
{
|
972
|
+
VariableReferenceErrorMessage(theEnv,exprPtr->lexemeValue,lastOne,
|
973
|
+
whichCE,slotName,theField);
|
974
|
+
return exprPtr;
|
975
|
+
}
|
976
|
+
else if (UnmatchableConstraint(exprPtr->constraints))
|
977
|
+
{
|
978
|
+
ConstraintReferenceErrorMessage(theEnv,exprPtr->lexemeValue,lastOne,i,
|
979
|
+
whichCE,slotName,theField);
|
980
|
+
return exprPtr;
|
981
|
+
}
|
982
|
+
}
|
983
|
+
|
984
|
+
/*==================================================*/
|
985
|
+
/* Check that multifield variables contained in the */
|
986
|
+
/* expression were previously defined in the LHS. */
|
987
|
+
/*==================================================*/
|
988
|
+
|
989
|
+
else if ((exprPtr->pnType == MF_VARIABLE_NODE) && (exprPtr->referringNode == NULL))
|
990
|
+
{
|
991
|
+
VariableReferenceErrorMessage(theEnv,exprPtr->lexemeValue,lastOne,
|
992
|
+
whichCE,slotName,theField);
|
993
|
+
return exprPtr;
|
994
|
+
}
|
995
|
+
|
996
|
+
/*=====================================================*/
|
997
|
+
/* Check that global variables are referenced properly */
|
998
|
+
/* (i.e. if you reference a global variable, it must */
|
999
|
+
/* already be defined by a defglobal construct). */
|
1000
|
+
/*=====================================================*/
|
1001
|
+
|
1002
|
+
#if DEFGLOBAL_CONSTRUCT
|
1003
|
+
else if (exprPtr->pnType == GBL_VARIABLE_NODE)
|
1004
|
+
{
|
1005
|
+
unsigned int count;
|
1006
|
+
|
1007
|
+
if (FindImportedConstruct(theEnv,"defglobal",NULL,exprPtr->lexemeValue->contents,
|
1008
|
+
&count,true,NULL) == NULL)
|
1009
|
+
{
|
1010
|
+
VariableReferenceErrorMessage(theEnv,exprPtr->lexemeValue,lastOne,
|
1011
|
+
whichCE,slotName,theField);
|
1012
|
+
return exprPtr;
|
1013
|
+
}
|
1014
|
+
}
|
1015
|
+
#endif
|
1016
|
+
|
1017
|
+
/*============================================*/
|
1018
|
+
/* Recursively check other function calls to */
|
1019
|
+
/* insure variables are referenced correctly. */
|
1020
|
+
/*============================================*/
|
1021
|
+
|
1022
|
+
else if (((exprPtr->pnType == FCALL_NODE)
|
1023
|
+
#if DEFGENERIC_CONSTRUCT
|
1024
|
+
|| (exprPtr->pnType == GCALL_NODE)
|
1025
|
+
#endif
|
1026
|
+
#if DEFFUNCTION_CONSTRUCT
|
1027
|
+
|| (exprPtr->pnType == PCALL_NODE)
|
1028
|
+
#endif
|
1029
|
+
) && (exprPtr->bottom != NULL))
|
1030
|
+
{
|
1031
|
+
if ((rv = CheckExpression(theEnv,exprPtr->bottom,exprPtr,whichCE,slotName,theField)) != NULL)
|
1032
|
+
{ return rv; }
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
/*=============================================*/
|
1036
|
+
/* Move on to the next part of the expression. */
|
1037
|
+
/*=============================================*/
|
1038
|
+
|
1039
|
+
i++;
|
1040
|
+
exprPtr = exprPtr->right;
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
/*================================================*/
|
1044
|
+
/* Return NULL to indicate no error was detected. */
|
1045
|
+
/*================================================*/
|
1046
|
+
|
1047
|
+
return NULL;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
/********************************************************/
|
1051
|
+
/* VariableReferenceErrorMessage: Generic error message */
|
1052
|
+
/* for referencing a variable before it is defined. */
|
1053
|
+
/********************************************************/
|
1054
|
+
static void VariableReferenceErrorMessage(
|
1055
|
+
Environment *theEnv,
|
1056
|
+
CLIPSLexeme *theVariable,
|
1057
|
+
struct lhsParseNode *theExpression,
|
1058
|
+
int whichCE,
|
1059
|
+
CLIPSLexeme *slotName,
|
1060
|
+
int theField)
|
1061
|
+
{
|
1062
|
+
struct expr *temprv;
|
1063
|
+
|
1064
|
+
/*=============================*/
|
1065
|
+
/* Print the error message ID. */
|
1066
|
+
/*=============================*/
|
1067
|
+
|
1068
|
+
PrintErrorID(theEnv,"ANALYSIS",4,true);
|
1069
|
+
|
1070
|
+
/*=================================*/
|
1071
|
+
/* Print the name of the variable. */
|
1072
|
+
/*=================================*/
|
1073
|
+
|
1074
|
+
WriteString(theEnv,STDERR,"Variable ?");
|
1075
|
+
WriteString(theEnv,STDERR,theVariable->contents);
|
1076
|
+
WriteString(theEnv,STDERR," ");
|
1077
|
+
|
1078
|
+
/*=================================================*/
|
1079
|
+
/* If the variable was found inside an expression, */
|
1080
|
+
/* then print the expression. */
|
1081
|
+
/*=================================================*/
|
1082
|
+
|
1083
|
+
if (theExpression != NULL)
|
1084
|
+
{
|
1085
|
+
whichCE = theExpression->whichCE;
|
1086
|
+
temprv = LHSParseNodesToExpression(theEnv,theExpression);
|
1087
|
+
ReturnExpression(theEnv,temprv->nextArg);
|
1088
|
+
temprv->nextArg = NULL;
|
1089
|
+
WriteString(theEnv,STDERR,"found in the expression ");
|
1090
|
+
PrintExpression(theEnv,STDERR,temprv);
|
1091
|
+
WriteString(theEnv,STDERR,"\n");
|
1092
|
+
ReturnExpression(theEnv,temprv);
|
1093
|
+
}
|
1094
|
+
|
1095
|
+
/*====================================================*/
|
1096
|
+
/* Print the CE in which the variable was referenced. */
|
1097
|
+
/*====================================================*/
|
1098
|
+
|
1099
|
+
WriteString(theEnv,STDERR,"was referenced in CE #");
|
1100
|
+
WriteInteger(theEnv,STDERR,whichCE);
|
1101
|
+
|
1102
|
+
/*=====================================*/
|
1103
|
+
/* Identify the slot or field in which */
|
1104
|
+
/* the variable was found. */
|
1105
|
+
/*=====================================*/
|
1106
|
+
|
1107
|
+
if (slotName == NULL)
|
1108
|
+
{
|
1109
|
+
if (theField > 0)
|
1110
|
+
{
|
1111
|
+
WriteString(theEnv,STDERR," field #");
|
1112
|
+
WriteInteger(theEnv,STDERR,theField);
|
1113
|
+
}
|
1114
|
+
}
|
1115
|
+
else
|
1116
|
+
{
|
1117
|
+
WriteString(theEnv,STDERR," slot '");
|
1118
|
+
WriteString(theEnv,STDERR,slotName->contents);
|
1119
|
+
WriteString(theEnv,STDERR,"'");
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
WriteString(theEnv,STDERR," before being defined.\n");
|
1123
|
+
}
|
1124
|
+
|
1125
|
+
/************************************************************/
|
1126
|
+
/* VariableMixingErrorMessage: Prints the error message for */
|
1127
|
+
/* the illegal mixing of single and multifield variables */
|
1128
|
+
/* on the LHS of a rule. */
|
1129
|
+
/************************************************************/
|
1130
|
+
static void VariableMixingErrorMessage(
|
1131
|
+
Environment *theEnv,
|
1132
|
+
CLIPSLexeme *theVariable)
|
1133
|
+
{
|
1134
|
+
PrintErrorID(theEnv,"ANALYSIS",3,true);
|
1135
|
+
WriteString(theEnv,STDERR,"Variable ?");
|
1136
|
+
WriteString(theEnv,STDERR,theVariable->contents);
|
1137
|
+
WriteString(theEnv,STDERR," is used as both a single and multifield variable in the LHS.\n");
|
1138
|
+
}
|
1139
|
+
|
1140
|
+
#endif /* (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT */
|
1141
|
+
|
1142
|
+
|