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,892 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.41 11/12/22 */
|
5
|
+
/* */
|
6
|
+
/* RULE CONSTRAINTS MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: Provides routines for detecting constraint */
|
11
|
+
/* conflicts in the LHS and RHS of rules. */
|
12
|
+
/* */
|
13
|
+
/* Principal Programmer(s): */
|
14
|
+
/* Gary D. Riley */
|
15
|
+
/* */
|
16
|
+
/* Contributing Programmer(s): */
|
17
|
+
/* */
|
18
|
+
/* Revision History: */
|
19
|
+
/* */
|
20
|
+
/* 6.24: Renamed BOOLEAN macro type to intBool. */
|
21
|
+
/* */
|
22
|
+
/* 6.30: Support for long long integers. */
|
23
|
+
/* */
|
24
|
+
/* 6.40: Pragma once and other inclusion changes. */
|
25
|
+
/* */
|
26
|
+
/* Added support for booleans with <stdbool.h>. */
|
27
|
+
/* */
|
28
|
+
/* Removed use of void pointers for specific */
|
29
|
+
/* data structures. */
|
30
|
+
/* */
|
31
|
+
/* Static constraint checking is always enabled. */
|
32
|
+
/* */
|
33
|
+
/* UDF redesign. */
|
34
|
+
/* */
|
35
|
+
/* 6.41: Fixed constraint violation error message that */
|
36
|
+
/* should be variable not found error. */
|
37
|
+
/* */
|
38
|
+
/*************************************************************/
|
39
|
+
|
40
|
+
#include "setup.h"
|
41
|
+
|
42
|
+
#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
|
43
|
+
|
44
|
+
#include <stdio.h>
|
45
|
+
|
46
|
+
#include "analysis.h"
|
47
|
+
#include "cstrnchk.h"
|
48
|
+
#include "cstrnops.h"
|
49
|
+
#include "cstrnutl.h"
|
50
|
+
#include "envrnmnt.h"
|
51
|
+
#include "extnfunc.h"
|
52
|
+
#include "prcdrpsr.h"
|
53
|
+
#include "prntutil.h"
|
54
|
+
#include "reorder.h"
|
55
|
+
#include "router.h"
|
56
|
+
#include "rulepsr.h"
|
57
|
+
|
58
|
+
#include "rulecstr.h"
|
59
|
+
|
60
|
+
/***************************************/
|
61
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
62
|
+
/***************************************/
|
63
|
+
|
64
|
+
static bool CheckForUnmatchableConstraints(Environment *,struct lhsParseNode *,unsigned short);
|
65
|
+
static bool MultifieldCardinalityViolation(Environment *,struct lhsParseNode *);
|
66
|
+
static struct lhsParseNode *UnionVariableConstraints(Environment *,struct lhsParseNode *,
|
67
|
+
struct lhsParseNode *);
|
68
|
+
static struct lhsParseNode *AddToVariableConstraints(Environment *,struct lhsParseNode *,
|
69
|
+
struct lhsParseNode *);
|
70
|
+
static void ConstraintConflictMessage(Environment *,CLIPSLexeme *,
|
71
|
+
unsigned short,unsigned short,CLIPSLexeme *);
|
72
|
+
static bool CheckArgumentForConstraintError(Environment *,struct expr *,struct expr*,
|
73
|
+
unsigned int,struct functionDefinition *,
|
74
|
+
struct lhsParseNode *);
|
75
|
+
|
76
|
+
/***********************************************************/
|
77
|
+
/* CheckForUnmatchableConstraints: Determines if a LHS CE */
|
78
|
+
/* node contains unmatchable constraints. Return true if */
|
79
|
+
/* there are unmatchable constraints, otherwise false. */
|
80
|
+
/***********************************************************/
|
81
|
+
static bool CheckForUnmatchableConstraints(
|
82
|
+
Environment *theEnv,
|
83
|
+
struct lhsParseNode *theNode,
|
84
|
+
unsigned short whichCE)
|
85
|
+
{
|
86
|
+
if (UnmatchableConstraint(theNode->constraints))
|
87
|
+
{
|
88
|
+
ConstraintConflictMessage(theEnv,theNode->lexemeValue,whichCE,
|
89
|
+
theNode->index,theNode->slot);
|
90
|
+
return true;
|
91
|
+
}
|
92
|
+
|
93
|
+
return false;
|
94
|
+
}
|
95
|
+
|
96
|
+
/******************************************************/
|
97
|
+
/* ConstraintConflictMessage: Error message used when */
|
98
|
+
/* a constraint restriction for a slot prevents any */
|
99
|
+
/* value from matching the pattern constraint. */
|
100
|
+
/******************************************************/
|
101
|
+
static void ConstraintConflictMessage(
|
102
|
+
Environment *theEnv,
|
103
|
+
CLIPSLexeme *variableName,
|
104
|
+
unsigned short thePattern,
|
105
|
+
unsigned short theField,
|
106
|
+
CLIPSLexeme *theSlot)
|
107
|
+
{
|
108
|
+
/*=========================*/
|
109
|
+
/* Print the error header. */
|
110
|
+
/*=========================*/
|
111
|
+
|
112
|
+
PrintErrorID(theEnv,"RULECSTR",1,true);
|
113
|
+
|
114
|
+
/*======================================================*/
|
115
|
+
/* Print the variable name (if available) and CE number */
|
116
|
+
/* for which the constraint violation occurred. */
|
117
|
+
/*======================================================*/
|
118
|
+
|
119
|
+
if (variableName != NULL)
|
120
|
+
{
|
121
|
+
WriteString(theEnv,STDERR,"Variable ?");
|
122
|
+
WriteString(theEnv,STDERR,variableName->contents);
|
123
|
+
WriteString(theEnv,STDERR," in CE #");
|
124
|
+
WriteInteger(theEnv,STDERR,thePattern);
|
125
|
+
}
|
126
|
+
else
|
127
|
+
{
|
128
|
+
WriteString(theEnv,STDERR,"Pattern #");
|
129
|
+
WriteInteger(theEnv,STDERR,thePattern);
|
130
|
+
}
|
131
|
+
|
132
|
+
/*=======================================*/
|
133
|
+
/* Print the slot name or field position */
|
134
|
+
/* in which the violation occurred. */
|
135
|
+
/*=======================================*/
|
136
|
+
|
137
|
+
if (theSlot == NULL)
|
138
|
+
{
|
139
|
+
WriteString(theEnv,STDERR," field #");
|
140
|
+
WriteInteger(theEnv,STDERR,theField);
|
141
|
+
}
|
142
|
+
else
|
143
|
+
{
|
144
|
+
WriteString(theEnv,STDERR," slot '");
|
145
|
+
WriteString(theEnv,STDERR,theSlot->contents);
|
146
|
+
WriteString(theEnv,STDERR,"'");
|
147
|
+
}
|
148
|
+
|
149
|
+
/*======================================*/
|
150
|
+
/* Print the rest of the error message. */
|
151
|
+
/*======================================*/
|
152
|
+
|
153
|
+
WriteString(theEnv,STDERR," has constraint conflicts which make the pattern unmatchable.\n");
|
154
|
+
}
|
155
|
+
|
156
|
+
/***************************************************************/
|
157
|
+
/* MultifieldCardinalityViolation: Determines if a cardinality */
|
158
|
+
/* violation has occurred for a LHS CE node. */
|
159
|
+
/***************************************************************/
|
160
|
+
static bool MultifieldCardinalityViolation(
|
161
|
+
Environment *theEnv,
|
162
|
+
struct lhsParseNode *theNode)
|
163
|
+
{
|
164
|
+
struct lhsParseNode *tmpNode;
|
165
|
+
struct expr *tmpMax;
|
166
|
+
long long minFields = 0;
|
167
|
+
long long maxFields = 0;
|
168
|
+
bool posInfinity = false;
|
169
|
+
CONSTRAINT_RECORD *newConstraint, *tempConstraint;
|
170
|
+
|
171
|
+
/*================================*/
|
172
|
+
/* A single field slot can't have */
|
173
|
+
/* a cardinality violation. */
|
174
|
+
/*================================*/
|
175
|
+
|
176
|
+
if (theNode->multifieldSlot == false) return false;
|
177
|
+
|
178
|
+
/*=============================================*/
|
179
|
+
/* Determine the minimum and maximum number of */
|
180
|
+
/* fields the slot could contain based on the */
|
181
|
+
/* slot constraints found in the pattern. */
|
182
|
+
/*=============================================*/
|
183
|
+
|
184
|
+
for (tmpNode = theNode->bottom;
|
185
|
+
tmpNode != NULL;
|
186
|
+
tmpNode = tmpNode->right)
|
187
|
+
{
|
188
|
+
/*====================================================*/
|
189
|
+
/* A single field variable increases both the minimum */
|
190
|
+
/* and maximum number of fields by one. */
|
191
|
+
/*====================================================*/
|
192
|
+
|
193
|
+
if ((tmpNode->pnType == SF_VARIABLE_NODE) ||
|
194
|
+
(tmpNode->pnType == SF_WILDCARD_NODE))
|
195
|
+
{
|
196
|
+
minFields++;
|
197
|
+
maxFields++;
|
198
|
+
}
|
199
|
+
|
200
|
+
/*=================================================*/
|
201
|
+
/* Otherwise a multifield wildcard or variable has */
|
202
|
+
/* been encountered. If it is constrained then use */
|
203
|
+
/* minimum and maximum number of fields constraint */
|
204
|
+
/* associated with this LHS node. */
|
205
|
+
/*=================================================*/
|
206
|
+
|
207
|
+
else if (tmpNode->constraints != NULL)
|
208
|
+
{
|
209
|
+
/*=======================================*/
|
210
|
+
/* The lowest minimum of all the min/max */
|
211
|
+
/* pairs will be the first in the list. */
|
212
|
+
/*=======================================*/
|
213
|
+
|
214
|
+
if (tmpNode->constraints->minFields->value != SymbolData(theEnv)->NegativeInfinity)
|
215
|
+
{ minFields += tmpNode->constraints->minFields->integerValue->contents; }
|
216
|
+
|
217
|
+
/*=========================================*/
|
218
|
+
/* The greatest maximum of all the min/max */
|
219
|
+
/* pairs will be the last in the list. */
|
220
|
+
/*=========================================*/
|
221
|
+
|
222
|
+
tmpMax = tmpNode->constraints->maxFields;
|
223
|
+
while (tmpMax->nextArg != NULL) tmpMax = tmpMax->nextArg;
|
224
|
+
if (tmpMax->value == SymbolData(theEnv)->PositiveInfinity)
|
225
|
+
{ posInfinity = true; }
|
226
|
+
else
|
227
|
+
{ maxFields += tmpMax->integerValue->contents; }
|
228
|
+
}
|
229
|
+
|
230
|
+
/*================================================*/
|
231
|
+
/* Otherwise an unconstrained multifield wildcard */
|
232
|
+
/* or variable increases the maximum number of */
|
233
|
+
/* fields to positive infinity. */
|
234
|
+
/*================================================*/
|
235
|
+
|
236
|
+
else
|
237
|
+
{ posInfinity = true; }
|
238
|
+
}
|
239
|
+
|
240
|
+
/*==================================================================*/
|
241
|
+
/* Create a constraint record for the cardinality of the sum of the */
|
242
|
+
/* cardinalities of the restrictions inside the multifield slot. */
|
243
|
+
/*==================================================================*/
|
244
|
+
|
245
|
+
if (theNode->constraints == NULL) tempConstraint = GetConstraintRecord(theEnv);
|
246
|
+
else tempConstraint = CopyConstraintRecord(theEnv,theNode->constraints);
|
247
|
+
ReturnExpression(theEnv,tempConstraint->minFields);
|
248
|
+
ReturnExpression(theEnv,tempConstraint->maxFields);
|
249
|
+
tempConstraint->minFields = GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,minFields));
|
250
|
+
if (posInfinity) tempConstraint->maxFields = GenConstant(theEnv,SYMBOL_TYPE,SymbolData(theEnv)->PositiveInfinity);
|
251
|
+
else tempConstraint->maxFields = GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,maxFields));
|
252
|
+
|
253
|
+
/*================================================================*/
|
254
|
+
/* Determine the final cardinality for the multifield slot by */
|
255
|
+
/* intersecting the cardinality sum of the restrictions within */
|
256
|
+
/* the multifield slot with the original cardinality of the slot. */
|
257
|
+
/*================================================================*/
|
258
|
+
|
259
|
+
newConstraint = IntersectConstraints(theEnv,theNode->constraints,tempConstraint);
|
260
|
+
if (theNode->derivedConstraints) RemoveConstraint(theEnv,theNode->constraints);
|
261
|
+
RemoveConstraint(theEnv,tempConstraint);
|
262
|
+
theNode->constraints = newConstraint;
|
263
|
+
theNode->derivedConstraints = true;
|
264
|
+
|
265
|
+
/*===================================================================*/
|
266
|
+
/* Determine if the final cardinality for the slot can be satisfied. */
|
267
|
+
/*===================================================================*/
|
268
|
+
|
269
|
+
if (UnmatchableConstraint(newConstraint)) return true;
|
270
|
+
|
271
|
+
return false;
|
272
|
+
}
|
273
|
+
|
274
|
+
/***************************************************/
|
275
|
+
/* ProcessConnectedConstraints: Examines a single */
|
276
|
+
/* connected constraint searching for constraint */
|
277
|
+
/* violations. */
|
278
|
+
/***************************************************/
|
279
|
+
bool ProcessConnectedConstraints(
|
280
|
+
Environment *theEnv,
|
281
|
+
struct lhsParseNode *theNode,
|
282
|
+
struct lhsParseNode *multifieldHeader,
|
283
|
+
struct lhsParseNode *patternHead)
|
284
|
+
{
|
285
|
+
struct constraintRecord *orConstraints = NULL, *andConstraints;
|
286
|
+
struct constraintRecord *tmpConstraints, *rvConstraints;
|
287
|
+
struct lhsParseNode *orNode, *andNode;
|
288
|
+
struct expr *tmpExpr;
|
289
|
+
|
290
|
+
/*============================================*/
|
291
|
+
/* Loop through all of the or (|) constraints */
|
292
|
+
/* found in the connected constraint. */
|
293
|
+
/*============================================*/
|
294
|
+
|
295
|
+
for (orNode = theNode->bottom; orNode != NULL; orNode = orNode->bottom)
|
296
|
+
{
|
297
|
+
/*=================================================*/
|
298
|
+
/* Intersect all of the &'ed constraints together. */
|
299
|
+
/*=================================================*/
|
300
|
+
|
301
|
+
andConstraints = NULL;
|
302
|
+
for (andNode = orNode; andNode != NULL; andNode = andNode->right)
|
303
|
+
{
|
304
|
+
if (! andNode->negated)
|
305
|
+
{
|
306
|
+
if (andNode->pnType == RETURN_VALUE_CONSTRAINT_NODE)
|
307
|
+
{
|
308
|
+
if (andNode->expression->pnType == FCALL_NODE)
|
309
|
+
{
|
310
|
+
rvConstraints = FunctionCallToConstraintRecord(theEnv,andNode->expression->value);
|
311
|
+
tmpConstraints = andConstraints;
|
312
|
+
andConstraints = IntersectConstraints(theEnv,andConstraints,rvConstraints);
|
313
|
+
RemoveConstraint(theEnv,tmpConstraints);
|
314
|
+
RemoveConstraint(theEnv,rvConstraints);
|
315
|
+
}
|
316
|
+
}
|
317
|
+
else if (ConstantNode(andNode))
|
318
|
+
{
|
319
|
+
tmpExpr = GenConstant(theEnv,NodeTypeToType(andNode),andNode->value);
|
320
|
+
rvConstraints = ExpressionToConstraintRecord(theEnv,tmpExpr);
|
321
|
+
tmpConstraints = andConstraints;
|
322
|
+
andConstraints = IntersectConstraints(theEnv,andConstraints,rvConstraints);
|
323
|
+
RemoveConstraint(theEnv,tmpConstraints);
|
324
|
+
RemoveConstraint(theEnv,rvConstraints);
|
325
|
+
ReturnExpression(theEnv,tmpExpr);
|
326
|
+
}
|
327
|
+
else if (andNode->constraints != NULL)
|
328
|
+
{
|
329
|
+
tmpConstraints = andConstraints;
|
330
|
+
andConstraints = IntersectConstraints(theEnv,andConstraints,andNode->constraints);
|
331
|
+
RemoveConstraint(theEnv,tmpConstraints);
|
332
|
+
}
|
333
|
+
}
|
334
|
+
}
|
335
|
+
|
336
|
+
/*===========================================================*/
|
337
|
+
/* Intersect the &'ed constraints with the slot constraints. */
|
338
|
+
/*===========================================================*/
|
339
|
+
|
340
|
+
tmpConstraints = andConstraints;
|
341
|
+
andConstraints = IntersectConstraints(theEnv,andConstraints,theNode->constraints);
|
342
|
+
RemoveConstraint(theEnv,tmpConstraints);
|
343
|
+
|
344
|
+
/*===============================================================*/
|
345
|
+
/* Remove any negated constants from the list of allowed values. */
|
346
|
+
/*===============================================================*/
|
347
|
+
|
348
|
+
for (andNode = orNode; andNode != NULL; andNode = andNode->right)
|
349
|
+
{
|
350
|
+
if ((andNode->negated) && ConstantNode(andNode))
|
351
|
+
{ RemoveConstantFromConstraint(theEnv,NodeTypeToType(andNode),andNode->value,andConstraints); }
|
352
|
+
}
|
353
|
+
|
354
|
+
/*=======================================================*/
|
355
|
+
/* Union the &'ed constraints with the |'ed constraints. */
|
356
|
+
/*=======================================================*/
|
357
|
+
|
358
|
+
tmpConstraints = orConstraints;
|
359
|
+
orConstraints = UnionConstraints(theEnv,orConstraints,andConstraints);
|
360
|
+
RemoveConstraint(theEnv,tmpConstraints);
|
361
|
+
RemoveConstraint(theEnv,andConstraints);
|
362
|
+
}
|
363
|
+
|
364
|
+
/*===============================================*/
|
365
|
+
/* Replace the constraints for the slot with the */
|
366
|
+
/* constraints derived from the connected */
|
367
|
+
/* constraints (which should be a subset. */
|
368
|
+
/*===============================================*/
|
369
|
+
|
370
|
+
if (orConstraints != NULL)
|
371
|
+
{
|
372
|
+
if (theNode->derivedConstraints) RemoveConstraint(theEnv,theNode->constraints);
|
373
|
+
theNode->constraints = orConstraints;
|
374
|
+
theNode->derivedConstraints = true;
|
375
|
+
}
|
376
|
+
|
377
|
+
/*==================================*/
|
378
|
+
/* Check for constraint violations. */
|
379
|
+
/*==================================*/
|
380
|
+
|
381
|
+
if (CheckForUnmatchableConstraints(theEnv,theNode,patternHead->whichCE))
|
382
|
+
{ return true; }
|
383
|
+
|
384
|
+
/*=========================================*/
|
385
|
+
/* If the constraints are for a multifield */
|
386
|
+
/* slot, check for cardinality violations. */
|
387
|
+
/*=========================================*/
|
388
|
+
|
389
|
+
if ((multifieldHeader != NULL) && (theNode->right == NULL))
|
390
|
+
{
|
391
|
+
if (MultifieldCardinalityViolation(theEnv,multifieldHeader))
|
392
|
+
{
|
393
|
+
ConstraintViolationErrorMessage(theEnv,"The group of restrictions",
|
394
|
+
NULL,false,
|
395
|
+
patternHead->whichCE,
|
396
|
+
multifieldHeader->slot,
|
397
|
+
multifieldHeader->index,
|
398
|
+
CARDINALITY_VIOLATION,
|
399
|
+
multifieldHeader->constraints,true);
|
400
|
+
return true;
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
/*=======================================*/
|
405
|
+
/* Return false indicating no constraint */
|
406
|
+
/* violations were detected. */
|
407
|
+
/*=======================================*/
|
408
|
+
|
409
|
+
return false;
|
410
|
+
}
|
411
|
+
|
412
|
+
/**************************************************/
|
413
|
+
/* ConstraintReferenceErrorMessage: Generic error */
|
414
|
+
/* message for LHS constraint violation errors */
|
415
|
+
/* that occur within an expression. */
|
416
|
+
/**************************************************/
|
417
|
+
void ConstraintReferenceErrorMessage(
|
418
|
+
Environment *theEnv,
|
419
|
+
CLIPSLexeme *theVariable,
|
420
|
+
struct lhsParseNode *theExpression,
|
421
|
+
int whichArgument,
|
422
|
+
int whichCE,
|
423
|
+
CLIPSLexeme *slotName,
|
424
|
+
int theField)
|
425
|
+
{
|
426
|
+
struct expr *temprv;
|
427
|
+
|
428
|
+
PrintErrorID(theEnv,"RULECSTR",2,true);
|
429
|
+
|
430
|
+
/*==========================*/
|
431
|
+
/* Print the variable name. */
|
432
|
+
/*==========================*/
|
433
|
+
|
434
|
+
WriteString(theEnv,STDERR,"Previous variable bindings of ?");
|
435
|
+
WriteString(theEnv,STDERR,theVariable->contents);
|
436
|
+
WriteString(theEnv,STDERR," caused the type restrictions");
|
437
|
+
|
438
|
+
/*============================*/
|
439
|
+
/* Print the argument number. */
|
440
|
+
/*============================*/
|
441
|
+
|
442
|
+
WriteString(theEnv,STDERR,"\nfor argument #");
|
443
|
+
WriteInteger(theEnv,STDERR,whichArgument);
|
444
|
+
|
445
|
+
/*=======================*/
|
446
|
+
/* Print the expression. */
|
447
|
+
/*=======================*/
|
448
|
+
|
449
|
+
WriteString(theEnv,STDERR," of the expression ");
|
450
|
+
temprv = LHSParseNodesToExpression(theEnv,theExpression);
|
451
|
+
ReturnExpression(theEnv,temprv->nextArg);
|
452
|
+
temprv->nextArg = NULL;
|
453
|
+
PrintExpression(theEnv,STDERR,temprv);
|
454
|
+
WriteString(theEnv,STDERR,"\n");
|
455
|
+
ReturnExpression(theEnv,temprv);
|
456
|
+
|
457
|
+
/*========================================*/
|
458
|
+
/* Print out the index of the conditional */
|
459
|
+
/* element and the slot name or field */
|
460
|
+
/* index where the violation occured. */
|
461
|
+
/*========================================*/
|
462
|
+
|
463
|
+
WriteString(theEnv,STDERR,"found in CE #");
|
464
|
+
WriteInteger(theEnv,STDERR,theExpression->whichCE);
|
465
|
+
if (slotName == NULL)
|
466
|
+
{
|
467
|
+
if (theField > 0)
|
468
|
+
{
|
469
|
+
WriteString(theEnv,STDERR," field #");
|
470
|
+
WriteInteger(theEnv,STDERR,theField);
|
471
|
+
}
|
472
|
+
}
|
473
|
+
else
|
474
|
+
{
|
475
|
+
WriteString(theEnv,STDERR," slot '");
|
476
|
+
WriteString(theEnv,STDERR,slotName->contents);
|
477
|
+
WriteString(theEnv,STDERR,"'");
|
478
|
+
}
|
479
|
+
|
480
|
+
WriteString(theEnv,STDERR," to be violated.\n");
|
481
|
+
}
|
482
|
+
|
483
|
+
/********************************************************/
|
484
|
+
/* AddToVariableConstraints: Adds the constraints for a */
|
485
|
+
/* variable to a list of constraints. If the variable */
|
486
|
+
/* is already in the list, the constraints for the */
|
487
|
+
/* variable are intersected with the new constraints. */
|
488
|
+
/********************************************************/
|
489
|
+
static struct lhsParseNode *AddToVariableConstraints(
|
490
|
+
Environment *theEnv,
|
491
|
+
struct lhsParseNode *oldList,
|
492
|
+
struct lhsParseNode *newItems)
|
493
|
+
{
|
494
|
+
CONSTRAINT_RECORD *newConstraints;
|
495
|
+
struct lhsParseNode *temp, *trace;
|
496
|
+
|
497
|
+
/*=================================================*/
|
498
|
+
/* Loop through each of the new constraints adding */
|
499
|
+
/* it to the list if it's not already present or */
|
500
|
+
/* modifying the constraint if it is. */
|
501
|
+
/*=================================================*/
|
502
|
+
|
503
|
+
while (newItems != NULL)
|
504
|
+
{
|
505
|
+
/*==========================================*/
|
506
|
+
/* Get the next item since the next pointer */
|
507
|
+
/* value (right) needs to be set to NULL. */
|
508
|
+
/*==========================================*/
|
509
|
+
|
510
|
+
temp = newItems->right;
|
511
|
+
newItems->right = NULL;
|
512
|
+
|
513
|
+
/*===================================*/
|
514
|
+
/* Search the list for the variable. */
|
515
|
+
/*===================================*/
|
516
|
+
|
517
|
+
for (trace = oldList; trace != NULL; trace = trace->right)
|
518
|
+
{
|
519
|
+
/*=========================================*/
|
520
|
+
/* If the variable is already in the list, */
|
521
|
+
/* modify the constraint already there to */
|
522
|
+
/* include the new constraint. */
|
523
|
+
/*=========================================*/
|
524
|
+
|
525
|
+
if (trace->value == newItems->value)
|
526
|
+
{
|
527
|
+
newConstraints = IntersectConstraints(theEnv,trace->constraints,
|
528
|
+
newItems->constraints);
|
529
|
+
RemoveConstraint(theEnv,trace->constraints);
|
530
|
+
trace->constraints = newConstraints;
|
531
|
+
ReturnLHSParseNodes(theEnv,newItems);
|
532
|
+
break;
|
533
|
+
}
|
534
|
+
}
|
535
|
+
|
536
|
+
/*=================================*/
|
537
|
+
/* Add the variable constraints to */
|
538
|
+
/* the list if it wasn't found. */
|
539
|
+
/*=================================*/
|
540
|
+
|
541
|
+
if (trace == NULL)
|
542
|
+
{
|
543
|
+
newItems->right = oldList;
|
544
|
+
oldList = newItems;
|
545
|
+
}
|
546
|
+
|
547
|
+
/*===========================*/
|
548
|
+
/* Move on to the next item. */
|
549
|
+
/*===========================*/
|
550
|
+
|
551
|
+
newItems = temp;
|
552
|
+
}
|
553
|
+
|
554
|
+
return(oldList);
|
555
|
+
}
|
556
|
+
|
557
|
+
/***********************************************************/
|
558
|
+
/* UnionVariableConstraints: Unions two lists of variable */
|
559
|
+
/* constraints. If a variable appears in one list but */
|
560
|
+
/* not the other, then the variable is unconstrained and */
|
561
|
+
/* thus not included in the unioned list. */
|
562
|
+
/***********************************************************/
|
563
|
+
static struct lhsParseNode *UnionVariableConstraints(
|
564
|
+
Environment *theEnv,
|
565
|
+
struct lhsParseNode *list1,
|
566
|
+
struct lhsParseNode *list2)
|
567
|
+
{
|
568
|
+
struct lhsParseNode *list3 = NULL, *trace, *temp;
|
569
|
+
|
570
|
+
/*===================================*/
|
571
|
+
/* Loop through all of the variables */
|
572
|
+
/* in the first list. */
|
573
|
+
/*===================================*/
|
574
|
+
|
575
|
+
while (list1 != NULL)
|
576
|
+
{
|
577
|
+
/*=============================================*/
|
578
|
+
/* Search for the variable in the second list. */
|
579
|
+
/*=============================================*/
|
580
|
+
|
581
|
+
for (trace = list2; trace != NULL; trace = trace->right)
|
582
|
+
{
|
583
|
+
/*============================================*/
|
584
|
+
/* If the variable is found in both lists, */
|
585
|
+
/* union the constraints and add the variable */
|
586
|
+
/* to the new list being constructed. */
|
587
|
+
/*============================================*/
|
588
|
+
|
589
|
+
if (list1->value == trace->value)
|
590
|
+
{
|
591
|
+
temp = GetLHSParseNode(theEnv);
|
592
|
+
temp->derivedConstraints = true;
|
593
|
+
temp->value = list1->value;
|
594
|
+
temp->constraints = UnionConstraints(theEnv,list1->constraints,trace->constraints);
|
595
|
+
temp->right = list3;
|
596
|
+
list3 = temp;
|
597
|
+
break;
|
598
|
+
}
|
599
|
+
}
|
600
|
+
|
601
|
+
/*==============================*/
|
602
|
+
/* Move on to the next variable */
|
603
|
+
/* in the first list. */
|
604
|
+
/*==============================*/
|
605
|
+
|
606
|
+
temp = list1->right;
|
607
|
+
list1->right = NULL;
|
608
|
+
ReturnLHSParseNodes(theEnv,list1);
|
609
|
+
list1 = temp;
|
610
|
+
}
|
611
|
+
|
612
|
+
/*====================================*/
|
613
|
+
/* Free the items in the second list. */
|
614
|
+
/*====================================*/
|
615
|
+
|
616
|
+
ReturnLHSParseNodes(theEnv,list2);
|
617
|
+
|
618
|
+
/*======================*/
|
619
|
+
/* Return the new list. */
|
620
|
+
/*======================*/
|
621
|
+
|
622
|
+
return(list3);
|
623
|
+
}
|
624
|
+
|
625
|
+
/*****************************************************************/
|
626
|
+
/* GetExpressionVarConstraints: Given an expression stored using */
|
627
|
+
/* the LHS parse node data structures, determines and returns */
|
628
|
+
/* the constraints on variables caused by that expression. For */
|
629
|
+
/* example, the expression (+ ?x 1) would imply a numeric type */
|
630
|
+
/* constraint for the variable ?x since the addition function */
|
631
|
+
/* expects numeric arguments. */
|
632
|
+
/*****************************************************************/
|
633
|
+
struct lhsParseNode *GetExpressionVarConstraints(
|
634
|
+
Environment *theEnv,
|
635
|
+
struct lhsParseNode *theExpression)
|
636
|
+
{
|
637
|
+
struct lhsParseNode *list1 = NULL, *list2;
|
638
|
+
|
639
|
+
for (; theExpression != NULL; theExpression = theExpression->bottom)
|
640
|
+
{
|
641
|
+
if (theExpression->right != NULL)
|
642
|
+
{
|
643
|
+
list2 = GetExpressionVarConstraints(theEnv,theExpression->right);
|
644
|
+
list1 = AddToVariableConstraints(theEnv,list2,list1);
|
645
|
+
}
|
646
|
+
|
647
|
+
if (theExpression->pnType == SF_VARIABLE_NODE)
|
648
|
+
{
|
649
|
+
list2 = GetLHSParseNode(theEnv);
|
650
|
+
if (theExpression->referringNode != NULL)
|
651
|
+
{ list2->pnType = theExpression->referringNode->pnType; }
|
652
|
+
else
|
653
|
+
{ list2->pnType = SF_VARIABLE_NODE; }
|
654
|
+
list2->value = theExpression->value;
|
655
|
+
list2->derivedConstraints = true;
|
656
|
+
list2->constraints = CopyConstraintRecord(theEnv,theExpression->constraints);
|
657
|
+
list1 = AddToVariableConstraints(theEnv,list2,list1);
|
658
|
+
}
|
659
|
+
}
|
660
|
+
|
661
|
+
return(list1);
|
662
|
+
}
|
663
|
+
|
664
|
+
/***********************************************/
|
665
|
+
/* DeriveVariableConstraints: Derives the list */
|
666
|
+
/* of variable constraints associated with a */
|
667
|
+
/* single connected constraint. */
|
668
|
+
/***********************************************/
|
669
|
+
struct lhsParseNode *DeriveVariableConstraints(
|
670
|
+
Environment *theEnv,
|
671
|
+
struct lhsParseNode *theNode)
|
672
|
+
{
|
673
|
+
struct lhsParseNode *orNode, *andNode;
|
674
|
+
struct lhsParseNode *list1, *list2, *list3 = NULL;
|
675
|
+
bool first = true;
|
676
|
+
|
677
|
+
/*===============================*/
|
678
|
+
/* Process the constraints for a */
|
679
|
+
/* single connected constraint. */
|
680
|
+
/*===============================*/
|
681
|
+
|
682
|
+
for (orNode = theNode->bottom; orNode != NULL; orNode = orNode->bottom)
|
683
|
+
{
|
684
|
+
/*=================================================*/
|
685
|
+
/* Intersect all of the &'ed constraints together. */
|
686
|
+
/*=================================================*/
|
687
|
+
|
688
|
+
list2 = NULL;
|
689
|
+
for (andNode = orNode; andNode != NULL; andNode = andNode->right)
|
690
|
+
{
|
691
|
+
if ((andNode->pnType == RETURN_VALUE_CONSTRAINT_NODE) ||
|
692
|
+
(andNode->pnType == PREDICATE_CONSTRAINT_NODE))
|
693
|
+
{
|
694
|
+
list1 = GetExpressionVarConstraints(theEnv,andNode->expression);
|
695
|
+
list2 = AddToVariableConstraints(theEnv,list2,list1);
|
696
|
+
}
|
697
|
+
}
|
698
|
+
|
699
|
+
if (first)
|
700
|
+
{
|
701
|
+
list3 = list2;
|
702
|
+
first = false;
|
703
|
+
}
|
704
|
+
else
|
705
|
+
{ list3 = UnionVariableConstraints(theEnv,list3,list2); }
|
706
|
+
}
|
707
|
+
|
708
|
+
return(list3);
|
709
|
+
}
|
710
|
+
|
711
|
+
/*******************************************/
|
712
|
+
/* CheckRHSForConstraintErrors: Checks the */
|
713
|
+
/* RHS of a rule for constraint errors. */
|
714
|
+
/*******************************************/
|
715
|
+
bool CheckRHSForConstraintErrors(
|
716
|
+
Environment *theEnv,
|
717
|
+
struct expr *expressionList,
|
718
|
+
struct lhsParseNode *theLHS)
|
719
|
+
{
|
720
|
+
struct functionDefinition *theFunction;
|
721
|
+
unsigned int i;
|
722
|
+
struct expr *lastOne = NULL, *checkList, *tmpPtr;
|
723
|
+
|
724
|
+
if (expressionList == NULL) return false;
|
725
|
+
|
726
|
+
for (checkList = expressionList;
|
727
|
+
checkList != NULL;
|
728
|
+
checkList = checkList->nextArg)
|
729
|
+
{
|
730
|
+
expressionList = checkList->argList;
|
731
|
+
i = 1;
|
732
|
+
if (checkList->type == FCALL)
|
733
|
+
{
|
734
|
+
lastOne = checkList;
|
735
|
+
theFunction = checkList->functionValue;
|
736
|
+
}
|
737
|
+
else
|
738
|
+
{ theFunction = NULL; }
|
739
|
+
|
740
|
+
while (expressionList != NULL)
|
741
|
+
{
|
742
|
+
if (CheckArgumentForConstraintError(theEnv,expressionList,lastOne,i,
|
743
|
+
theFunction,theLHS))
|
744
|
+
{ return true; }
|
745
|
+
|
746
|
+
i++;
|
747
|
+
tmpPtr = expressionList->nextArg;
|
748
|
+
expressionList->nextArg = NULL;
|
749
|
+
if (CheckRHSForConstraintErrors(theEnv,expressionList,theLHS))
|
750
|
+
{
|
751
|
+
expressionList->nextArg = tmpPtr;
|
752
|
+
return true;
|
753
|
+
}
|
754
|
+
expressionList->nextArg = tmpPtr;
|
755
|
+
expressionList = expressionList->nextArg;
|
756
|
+
}
|
757
|
+
}
|
758
|
+
|
759
|
+
return false;
|
760
|
+
}
|
761
|
+
|
762
|
+
/*************************************************************/
|
763
|
+
/* CheckArgumentForConstraintError: Checks a single argument */
|
764
|
+
/* found in the RHS of a rule for constraint errors. */
|
765
|
+
/* Returns true if an error is detected, otherwise false. */
|
766
|
+
/*************************************************************/
|
767
|
+
static bool CheckArgumentForConstraintError(
|
768
|
+
Environment *theEnv,
|
769
|
+
struct expr *expressionList,
|
770
|
+
struct expr *lastOne,
|
771
|
+
unsigned int i,
|
772
|
+
struct functionDefinition *theFunction,
|
773
|
+
struct lhsParseNode *theLHS)
|
774
|
+
{
|
775
|
+
unsigned theRestriction2;
|
776
|
+
CONSTRAINT_RECORD *constraint1, *constraint2, *constraint3, *constraint4;
|
777
|
+
struct lhsParseNode *theVariable;
|
778
|
+
struct expr *tmpPtr;
|
779
|
+
bool rv = false;
|
780
|
+
|
781
|
+
/*=============================================================*/
|
782
|
+
/* Skip anything that isn't a variable or isn't an argument to */
|
783
|
+
/* a user defined function (i.e. deffunctions and generic have */
|
784
|
+
/* no constraint information so they aren't checked). */
|
785
|
+
/*=============================================================*/
|
786
|
+
|
787
|
+
if ((expressionList->type != SF_VARIABLE) || (theFunction == NULL))
|
788
|
+
{ return (rv); }
|
789
|
+
|
790
|
+
/*===========================================*/
|
791
|
+
/* Get the restrictions for the argument and */
|
792
|
+
/* convert them to a constraint record. */
|
793
|
+
/*===========================================*/
|
794
|
+
|
795
|
+
theRestriction2 = GetNthRestriction(theEnv,theFunction,i);
|
796
|
+
constraint1 = ArgumentTypeToConstraintRecord(theEnv,theRestriction2);
|
797
|
+
|
798
|
+
/*================================================*/
|
799
|
+
/* Look for the constraint record associated with */
|
800
|
+
/* binding the variable in the LHS of the rule. */
|
801
|
+
/*================================================*/
|
802
|
+
|
803
|
+
theVariable = FindVariable(expressionList->lexemeValue,theLHS);
|
804
|
+
if (theVariable != NULL)
|
805
|
+
{
|
806
|
+
if (theVariable->pnType == MF_VARIABLE_NODE)
|
807
|
+
{
|
808
|
+
constraint2 = GetConstraintRecord(theEnv);
|
809
|
+
SetConstraintType(MULTIFIELD_TYPE,constraint2);
|
810
|
+
}
|
811
|
+
else if (theVariable->constraints == NULL)
|
812
|
+
{ constraint2 = GetConstraintRecord(theEnv); }
|
813
|
+
else
|
814
|
+
{ constraint2 = CopyConstraintRecord(theEnv,theVariable->constraints); }
|
815
|
+
}
|
816
|
+
else
|
817
|
+
{ constraint2 = NULL; }
|
818
|
+
|
819
|
+
/*================================================*/
|
820
|
+
/* Look for the constraint record associated with */
|
821
|
+
/* binding the variable on the RHS of the rule. */
|
822
|
+
/*================================================*/
|
823
|
+
|
824
|
+
constraint3 = FindBindConstraints(theEnv,expressionList->lexemeValue);
|
825
|
+
|
826
|
+
/*==================================================*/
|
827
|
+
/* If the variable wasn't bound in the LHS or RHS, */
|
828
|
+
/* then a constraint violation won't be flagged. */
|
829
|
+
/* Other code will flag the unbound variable issue. */
|
830
|
+
/*==================================================*/
|
831
|
+
|
832
|
+
if ((constraint2 == NULL) && (constraint3 == NULL))
|
833
|
+
{
|
834
|
+
RemoveConstraint(theEnv,constraint1);
|
835
|
+
return(rv);
|
836
|
+
}
|
837
|
+
|
838
|
+
/*====================================================*/
|
839
|
+
/* Union the LHS and RHS variable binding constraints */
|
840
|
+
/* (the variable must satisfy one or the other). */
|
841
|
+
/*====================================================*/
|
842
|
+
|
843
|
+
constraint3 = UnionConstraints(theEnv,constraint3,constraint2);
|
844
|
+
|
845
|
+
/*====================================================*/
|
846
|
+
/* Intersect the LHS/RHS variable binding constraints */
|
847
|
+
/* with the function argument restriction constraints */
|
848
|
+
/* (the variable must satisfy both). */
|
849
|
+
/*====================================================*/
|
850
|
+
|
851
|
+
constraint4 = IntersectConstraints(theEnv,constraint3,constraint1);
|
852
|
+
|
853
|
+
/*====================================*/
|
854
|
+
/* Check for unmatchable constraints. */
|
855
|
+
/*====================================*/
|
856
|
+
|
857
|
+
if (UnmatchableConstraint(constraint4))
|
858
|
+
{
|
859
|
+
PrintErrorID(theEnv,"RULECSTR",3,true);
|
860
|
+
WriteString(theEnv,STDERR,"Previous variable bindings of ?");
|
861
|
+
WriteString(theEnv,STDERR,expressionList->lexemeValue->contents);
|
862
|
+
WriteString(theEnv,STDERR," caused the type restrictions");
|
863
|
+
WriteString(theEnv,STDERR,"\nfor argument #");
|
864
|
+
WriteInteger(theEnv,STDERR,i);
|
865
|
+
WriteString(theEnv,STDERR," of the expression ");
|
866
|
+
tmpPtr = lastOne->nextArg;
|
867
|
+
lastOne->nextArg = NULL;
|
868
|
+
PrintExpression(theEnv,STDERR,lastOne);
|
869
|
+
lastOne->nextArg = tmpPtr;
|
870
|
+
WriteString(theEnv,STDERR," found in the rule's RHS to be violated.\n");
|
871
|
+
|
872
|
+
rv = true;
|
873
|
+
}
|
874
|
+
|
875
|
+
/*===========================================*/
|
876
|
+
/* Free the temporarily created constraints. */
|
877
|
+
/*===========================================*/
|
878
|
+
|
879
|
+
RemoveConstraint(theEnv,constraint1);
|
880
|
+
RemoveConstraint(theEnv,constraint2);
|
881
|
+
RemoveConstraint(theEnv,constraint3);
|
882
|
+
RemoveConstraint(theEnv,constraint4);
|
883
|
+
|
884
|
+
/*========================================*/
|
885
|
+
/* Return true if unmatchable constraints */
|
886
|
+
/* were detected, otherwise false. */
|
887
|
+
/*========================================*/
|
888
|
+
|
889
|
+
return(rv);
|
890
|
+
}
|
891
|
+
|
892
|
+
#endif /* (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT */
|