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,1618 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.40 11/01/16 */
|
5
|
+
/* */
|
6
|
+
/* */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: Generic Functions Parsing Routines */
|
11
|
+
/* */
|
12
|
+
/* Principal Programmer(s): */
|
13
|
+
/* Brian L. Dantes */
|
14
|
+
/* */
|
15
|
+
/* Contributing Programmer(s): */
|
16
|
+
/* */
|
17
|
+
/* Revision History: */
|
18
|
+
/* */
|
19
|
+
/* 6.24: Renamed BOOLEAN macro type to intBool. */
|
20
|
+
/* */
|
21
|
+
/* If the last construct in a loaded file is a */
|
22
|
+
/* deffunction or defmethod with no closing right */
|
23
|
+
/* parenthesis, an error should be issued, but is */
|
24
|
+
/* not. DR0872 */
|
25
|
+
/* */
|
26
|
+
/* 6.30: Changed integer type/precision. */
|
27
|
+
/* */
|
28
|
+
/* GetConstructNameAndComment API change. */
|
29
|
+
/* */
|
30
|
+
/* Support for long long integers. */
|
31
|
+
/* */
|
32
|
+
/* Used gensprintf instead of sprintf. */
|
33
|
+
/* */
|
34
|
+
/* Added const qualifiers to remove C++ */
|
35
|
+
/* deprecation warnings. */
|
36
|
+
/* */
|
37
|
+
/* Converted API macros to function calls. */
|
38
|
+
/* */
|
39
|
+
/* Fixed linkage issue when BLOAD_AND_SAVE */
|
40
|
+
/* compiler flag is set to 0. */
|
41
|
+
/* */
|
42
|
+
/* Fixed typing issue when OBJECT_SYSTEM */
|
43
|
+
/* compiler flag is set to 0. */
|
44
|
+
/* */
|
45
|
+
/* Changed find construct functionality so that */
|
46
|
+
/* imported modules are search when locating a */
|
47
|
+
/* named construct. */
|
48
|
+
/* */
|
49
|
+
/* 6.40: Pragma once and other inclusion changes. */
|
50
|
+
/* */
|
51
|
+
/* Added support for booleans with <stdbool.h>. */
|
52
|
+
/* */
|
53
|
+
/* Removed use of void pointers for specific */
|
54
|
+
/* data structures. */
|
55
|
+
/* */
|
56
|
+
/*************************************************************/
|
57
|
+
|
58
|
+
/* =========================================
|
59
|
+
*****************************************
|
60
|
+
EXTERNAL DEFINITIONS
|
61
|
+
=========================================
|
62
|
+
***************************************** */
|
63
|
+
|
64
|
+
#include "setup.h"
|
65
|
+
|
66
|
+
#if DEFGENERIC_CONSTRUCT && (! BLOAD_ONLY) && (! RUN_TIME)
|
67
|
+
|
68
|
+
#if BLOAD || BLOAD_AND_BSAVE
|
69
|
+
#include "bload.h"
|
70
|
+
#endif
|
71
|
+
|
72
|
+
#if DEFFUNCTION_CONSTRUCT
|
73
|
+
#include "dffnxfun.h"
|
74
|
+
#endif
|
75
|
+
|
76
|
+
#if OBJECT_SYSTEM
|
77
|
+
#include "classfun.h"
|
78
|
+
#include "classcom.h"
|
79
|
+
#endif
|
80
|
+
|
81
|
+
#include "cstrccom.h"
|
82
|
+
#include "cstrcpsr.h"
|
83
|
+
#include "envrnmnt.h"
|
84
|
+
#include "exprnpsr.h"
|
85
|
+
#include "genrccom.h"
|
86
|
+
#include "immthpsr.h"
|
87
|
+
#include "memalloc.h"
|
88
|
+
#include "modulutl.h"
|
89
|
+
#include "pprint.h"
|
90
|
+
#include "prcdrpsr.h"
|
91
|
+
#include "prccode.h"
|
92
|
+
#include "prntutil.h"
|
93
|
+
#include "router.h"
|
94
|
+
#include "scanner.h"
|
95
|
+
#include "sysdep.h"
|
96
|
+
|
97
|
+
#include "genrcpsr.h"
|
98
|
+
|
99
|
+
/* =========================================
|
100
|
+
*****************************************
|
101
|
+
CONSTANTS
|
102
|
+
=========================================
|
103
|
+
***************************************** */
|
104
|
+
#define HIGHER_PRECEDENCE -1
|
105
|
+
#define IDENTICAL 0
|
106
|
+
#define LOWER_PRECEDENCE 1
|
107
|
+
|
108
|
+
#define CURR_ARG_VAR "current-argument"
|
109
|
+
|
110
|
+
#define PARAMETER_ERROR USHRT_MAX
|
111
|
+
|
112
|
+
/* =========================================
|
113
|
+
*****************************************
|
114
|
+
INTERNALLY VISIBLE FUNCTION HEADERS
|
115
|
+
=========================================
|
116
|
+
***************************************** */
|
117
|
+
|
118
|
+
static bool ValidGenericName(Environment *,const char *);
|
119
|
+
static CLIPSLexeme *ParseMethodNameAndIndex(Environment *,const char *,unsigned short *,struct token *);
|
120
|
+
|
121
|
+
#if DEBUGGING_FUNCTIONS
|
122
|
+
static void CreateDefaultGenericPPForm(Environment *,Defgeneric *);
|
123
|
+
#endif
|
124
|
+
|
125
|
+
static unsigned short ParseMethodParameters(Environment *,const char *,Expression **,CLIPSLexeme **,struct token *);
|
126
|
+
static RESTRICTION *ParseRestriction(Environment *,const char *);
|
127
|
+
static void ReplaceCurrentArgRefs(Environment *,Expression *);
|
128
|
+
static bool DuplicateParameters(Environment *,Expression *,Expression **,CLIPSLexeme *);
|
129
|
+
static Expression *AddParameter(Environment *,Expression *,Expression *,CLIPSLexeme *,RESTRICTION *);
|
130
|
+
static Expression *ValidType(Environment *,CLIPSLexeme *);
|
131
|
+
static bool RedundantClasses(Environment *,void *,void *);
|
132
|
+
static Defgeneric *AddGeneric(Environment *,CLIPSLexeme *,bool *);
|
133
|
+
static Defmethod *AddGenericMethod(Environment *,Defgeneric *,int,unsigned short);
|
134
|
+
static int RestrictionsCompare(Expression *,int,int,int,Defmethod *);
|
135
|
+
static int TypeListCompare(RESTRICTION *,RESTRICTION *);
|
136
|
+
static Defgeneric *NewGeneric(Environment *,CLIPSLexeme *);
|
137
|
+
|
138
|
+
/* =========================================
|
139
|
+
*****************************************
|
140
|
+
EXTERNALLY VISIBLE FUNCTIONS
|
141
|
+
=========================================
|
142
|
+
***************************************** */
|
143
|
+
|
144
|
+
/***************************************************************************
|
145
|
+
NAME : ParseDefgeneric
|
146
|
+
DESCRIPTION : Parses the defgeneric construct
|
147
|
+
INPUTS : The input logical name
|
148
|
+
RETURNS : False if successful parse, true otherwise
|
149
|
+
SIDE EFFECTS : Inserts valid generic function defn into generic entry
|
150
|
+
NOTES : H/L Syntax :
|
151
|
+
(defgeneric <name> [<comment>])
|
152
|
+
***************************************************************************/
|
153
|
+
bool ParseDefgeneric(
|
154
|
+
Environment *theEnv,
|
155
|
+
const char *readSource)
|
156
|
+
{
|
157
|
+
CLIPSLexeme *gname;
|
158
|
+
Defgeneric *gfunc;
|
159
|
+
bool newGeneric;
|
160
|
+
struct token genericInputToken;
|
161
|
+
|
162
|
+
SetPPBufferStatus(theEnv,true);
|
163
|
+
FlushPPBuffer(theEnv);
|
164
|
+
SavePPBuffer(theEnv,"(defgeneric ");
|
165
|
+
SetIndentDepth(theEnv,3);
|
166
|
+
|
167
|
+
#if BLOAD || BLOAD_AND_BSAVE
|
168
|
+
if ((Bloaded(theEnv) == true) && (! ConstructData(theEnv)->CheckSyntaxMode))
|
169
|
+
{
|
170
|
+
CannotLoadWithBloadMessage(theEnv,"defgeneric");
|
171
|
+
return true;
|
172
|
+
}
|
173
|
+
#endif
|
174
|
+
|
175
|
+
gname = GetConstructNameAndComment(theEnv,readSource,&genericInputToken,"defgeneric",
|
176
|
+
(FindConstructFunction *) FindDefgenericInModule,
|
177
|
+
NULL,"^",true,true,true,false);
|
178
|
+
if (gname == NULL)
|
179
|
+
return true;
|
180
|
+
|
181
|
+
if (ValidGenericName(theEnv,gname->contents) == false)
|
182
|
+
return true;
|
183
|
+
|
184
|
+
if (genericInputToken.tknType != RIGHT_PARENTHESIS_TOKEN)
|
185
|
+
{
|
186
|
+
PrintErrorID(theEnv,"GENRCPSR",1,false);
|
187
|
+
WriteString(theEnv,STDERR,"Expected ')' to complete defgeneric.\n");
|
188
|
+
return true;
|
189
|
+
}
|
190
|
+
SavePPBuffer(theEnv,"\n");
|
191
|
+
|
192
|
+
/* ========================================================
|
193
|
+
If we're only checking syntax, don't add the
|
194
|
+
successfully parsed deffacts to the KB.
|
195
|
+
======================================================== */
|
196
|
+
|
197
|
+
if (ConstructData(theEnv)->CheckSyntaxMode)
|
198
|
+
{ return false; }
|
199
|
+
|
200
|
+
gfunc = AddGeneric(theEnv,gname,&newGeneric);
|
201
|
+
|
202
|
+
#if DEBUGGING_FUNCTIONS
|
203
|
+
SetDefgenericPPForm(theEnv,gfunc,GetConserveMemory(theEnv) ? NULL : CopyPPBuffer(theEnv));
|
204
|
+
#endif
|
205
|
+
return false;
|
206
|
+
}
|
207
|
+
|
208
|
+
/***************************************************************************
|
209
|
+
NAME : ParseDefmethod
|
210
|
+
DESCRIPTION : Parses the defmethod construct
|
211
|
+
INPUTS : The input logical name
|
212
|
+
RETURNS : False if successful parse, true otherwise
|
213
|
+
SIDE EFFECTS : Inserts valid method definition into generic entry
|
214
|
+
NOTES : H/L Syntax :
|
215
|
+
(defmethod <name> [<index>] [<comment>]
|
216
|
+
(<restriction>* [<wildcard>])
|
217
|
+
<action>*)
|
218
|
+
<restriction> :== ?<name> |
|
219
|
+
(?<name> <type>* [<restriction-query>])
|
220
|
+
<wildcard> :== $?<name> |
|
221
|
+
($?<name> <type>* [<restriction-query>])
|
222
|
+
***************************************************************************/
|
223
|
+
bool ParseDefmethod(
|
224
|
+
Environment *theEnv,
|
225
|
+
const char *readSource)
|
226
|
+
{
|
227
|
+
CLIPSLexeme *gname;
|
228
|
+
unsigned short rcnt;
|
229
|
+
int mposn;
|
230
|
+
unsigned short mi;
|
231
|
+
unsigned short lvars;
|
232
|
+
bool newMethod;
|
233
|
+
bool mnew = false;
|
234
|
+
bool error;
|
235
|
+
Expression *params,*actions,*tmp;
|
236
|
+
CLIPSLexeme *wildcard;
|
237
|
+
Defmethod *meth;
|
238
|
+
Defgeneric *gfunc;
|
239
|
+
unsigned short theIndex;
|
240
|
+
struct token genericInputToken;
|
241
|
+
|
242
|
+
SetPPBufferStatus(theEnv,true);
|
243
|
+
FlushPPBuffer(theEnv);
|
244
|
+
SetIndentDepth(theEnv,3);
|
245
|
+
SavePPBuffer(theEnv,"(defmethod ");
|
246
|
+
|
247
|
+
#if BLOAD || BLOAD_AND_BSAVE
|
248
|
+
if ((Bloaded(theEnv) == true) && (! ConstructData(theEnv)->CheckSyntaxMode))
|
249
|
+
{
|
250
|
+
CannotLoadWithBloadMessage(theEnv,"defmethod");
|
251
|
+
return true;
|
252
|
+
}
|
253
|
+
#endif
|
254
|
+
|
255
|
+
gname = ParseMethodNameAndIndex(theEnv,readSource,&theIndex,&genericInputToken);
|
256
|
+
if (gname == NULL)
|
257
|
+
return true;
|
258
|
+
|
259
|
+
if (ValidGenericName(theEnv,gname->contents) == false)
|
260
|
+
return true;
|
261
|
+
|
262
|
+
/* ========================================================
|
263
|
+
Go ahead and add the header so that the generic function
|
264
|
+
can be called recursively
|
265
|
+
======================================================== */
|
266
|
+
gfunc = AddGeneric(theEnv,gname,&newMethod);
|
267
|
+
|
268
|
+
#if DEBUGGING_FUNCTIONS
|
269
|
+
if (newMethod && (! ConstructData(theEnv)->CheckSyntaxMode))
|
270
|
+
CreateDefaultGenericPPForm(theEnv,gfunc);
|
271
|
+
#endif
|
272
|
+
|
273
|
+
IncrementIndentDepth(theEnv,1);
|
274
|
+
rcnt = ParseMethodParameters(theEnv,readSource,¶ms,&wildcard,&genericInputToken);
|
275
|
+
DecrementIndentDepth(theEnv,1);
|
276
|
+
if (rcnt == PARAMETER_ERROR)
|
277
|
+
goto DefmethodParseError;
|
278
|
+
PPCRAndIndent(theEnv);
|
279
|
+
for (tmp = params ; tmp != NULL ; tmp = tmp->nextArg)
|
280
|
+
{
|
281
|
+
ReplaceCurrentArgRefs(theEnv,((RESTRICTION *) tmp->argList)->query);
|
282
|
+
if (ReplaceProcVars(theEnv,"method",((RESTRICTION *) tmp->argList)->query,
|
283
|
+
params,wildcard,NULL,NULL))
|
284
|
+
{
|
285
|
+
DeleteTempRestricts(theEnv,params);
|
286
|
+
goto DefmethodParseError;
|
287
|
+
}
|
288
|
+
}
|
289
|
+
meth = FindMethodByRestrictions(gfunc,params,rcnt,wildcard,&mposn);
|
290
|
+
error = false;
|
291
|
+
if (meth != NULL)
|
292
|
+
{
|
293
|
+
if (meth->system)
|
294
|
+
{
|
295
|
+
PrintErrorID(theEnv,"GENRCPSR",17,false);
|
296
|
+
WriteString(theEnv,STDERR,"Cannot replace the implicit system method #");
|
297
|
+
PrintUnsignedInteger(theEnv,STDERR,meth->index);
|
298
|
+
WriteString(theEnv,STDERR,".\n");
|
299
|
+
error = true;
|
300
|
+
}
|
301
|
+
else if ((theIndex != 0) && (theIndex != meth->index))
|
302
|
+
{
|
303
|
+
PrintErrorID(theEnv,"GENRCPSR",2,false);
|
304
|
+
WriteString(theEnv,STDERR,"New method #");
|
305
|
+
PrintUnsignedInteger(theEnv,STDERR,theIndex);
|
306
|
+
WriteString(theEnv,STDERR," would be indistinguishable from method #");
|
307
|
+
PrintUnsignedInteger(theEnv,STDERR,meth->index);
|
308
|
+
WriteString(theEnv,STDERR,".\n");
|
309
|
+
error = true;
|
310
|
+
}
|
311
|
+
}
|
312
|
+
else if (theIndex != 0)
|
313
|
+
{
|
314
|
+
mi = FindMethodByIndex(gfunc,theIndex);
|
315
|
+
if (mi == METHOD_NOT_FOUND)
|
316
|
+
mnew = true;
|
317
|
+
else if (gfunc->methods[mi].system)
|
318
|
+
{
|
319
|
+
PrintErrorID(theEnv,"GENRCPSR",17,false);
|
320
|
+
WriteString(theEnv,STDERR,"Cannot replace the implicit system method #");
|
321
|
+
PrintUnsignedInteger(theEnv,STDERR,theIndex);
|
322
|
+
WriteString(theEnv,STDERR,".\n");
|
323
|
+
error = true;
|
324
|
+
}
|
325
|
+
}
|
326
|
+
else
|
327
|
+
mnew = true;
|
328
|
+
if (error)
|
329
|
+
{
|
330
|
+
DeleteTempRestricts(theEnv,params);
|
331
|
+
goto DefmethodParseError;
|
332
|
+
}
|
333
|
+
ExpressionData(theEnv)->ReturnContext = true;
|
334
|
+
actions = ParseProcActions(theEnv,"method",readSource,
|
335
|
+
&genericInputToken,params,wildcard,
|
336
|
+
NULL,NULL,&lvars,NULL);
|
337
|
+
|
338
|
+
/*===========================================================*/
|
339
|
+
/* Check for the closing right parenthesis of the defmethod. */
|
340
|
+
/*===========================================================*/
|
341
|
+
|
342
|
+
if ((genericInputToken.tknType != RIGHT_PARENTHESIS_TOKEN) && /* DR0872 */
|
343
|
+
(actions != NULL))
|
344
|
+
{
|
345
|
+
SyntaxErrorMessage(theEnv,"defmethod");
|
346
|
+
DeleteTempRestricts(theEnv,params);
|
347
|
+
ReturnPackedExpression(theEnv,actions);
|
348
|
+
goto DefmethodParseError;
|
349
|
+
}
|
350
|
+
|
351
|
+
if (actions == NULL)
|
352
|
+
{
|
353
|
+
DeleteTempRestricts(theEnv,params);
|
354
|
+
goto DefmethodParseError;
|
355
|
+
}
|
356
|
+
|
357
|
+
/*==============================================*/
|
358
|
+
/* If we're only checking syntax, don't add the */
|
359
|
+
/* successfully parsed deffunction to the KB. */
|
360
|
+
/*==============================================*/
|
361
|
+
|
362
|
+
if (ConstructData(theEnv)->CheckSyntaxMode)
|
363
|
+
{
|
364
|
+
DeleteTempRestricts(theEnv,params);
|
365
|
+
ReturnPackedExpression(theEnv,actions);
|
366
|
+
if (newMethod)
|
367
|
+
{
|
368
|
+
RemoveConstructFromModule(theEnv,&gfunc->header);
|
369
|
+
RemoveDefgeneric(theEnv,gfunc);
|
370
|
+
}
|
371
|
+
return false;
|
372
|
+
}
|
373
|
+
|
374
|
+
PPBackup(theEnv);
|
375
|
+
PPBackup(theEnv);
|
376
|
+
SavePPBuffer(theEnv,genericInputToken.printForm);
|
377
|
+
SavePPBuffer(theEnv,"\n");
|
378
|
+
|
379
|
+
#if DEBUGGING_FUNCTIONS
|
380
|
+
meth = AddMethod(theEnv,gfunc,meth,mposn,theIndex,params,rcnt,lvars,wildcard,actions,
|
381
|
+
GetConserveMemory(theEnv) ? NULL : CopyPPBuffer(theEnv),false);
|
382
|
+
#else
|
383
|
+
meth = AddMethod(theEnv,gfunc,meth,mposn,theIndex,params,rcnt,lvars,wildcard,actions,NULL,false);
|
384
|
+
#endif
|
385
|
+
DeleteTempRestricts(theEnv,params);
|
386
|
+
if (GetPrintWhileLoading(theEnv) && GetCompilationsWatch(theEnv) &&
|
387
|
+
(! ConstructData(theEnv)->CheckSyntaxMode))
|
388
|
+
{
|
389
|
+
const char *outRouter = STDOUT;
|
390
|
+
|
391
|
+
if (mnew)
|
392
|
+
{
|
393
|
+
WriteString(theEnv,outRouter," Method #");
|
394
|
+
PrintUnsignedInteger(theEnv,outRouter,meth->index);
|
395
|
+
WriteString(theEnv,outRouter," defined.\n");
|
396
|
+
}
|
397
|
+
else
|
398
|
+
{
|
399
|
+
outRouter = STDWRN;
|
400
|
+
PrintWarningID(theEnv,"CSTRCPSR",1,true);
|
401
|
+
WriteString(theEnv,outRouter,"Method #");
|
402
|
+
PrintUnsignedInteger(theEnv,outRouter,meth->index);
|
403
|
+
WriteString(theEnv,outRouter," redefined.\n");
|
404
|
+
}
|
405
|
+
}
|
406
|
+
return false;
|
407
|
+
|
408
|
+
DefmethodParseError:
|
409
|
+
if (newMethod)
|
410
|
+
{
|
411
|
+
RemoveConstructFromModule(theEnv,&gfunc->header);
|
412
|
+
RemoveDefgeneric(theEnv,gfunc);
|
413
|
+
}
|
414
|
+
return true;
|
415
|
+
}
|
416
|
+
|
417
|
+
/************************************************************************
|
418
|
+
NAME : AddMethod
|
419
|
+
DESCRIPTION : (Re)defines a new method for a generic
|
420
|
+
If method already exists, deletes old information
|
421
|
+
before proceeding.
|
422
|
+
INPUTS : 1) The generic address
|
423
|
+
2) The old method address (can be NULL)
|
424
|
+
3) The old method array position (can be -1)
|
425
|
+
4) The method index to assign (0 if don't care)
|
426
|
+
5) The parameter expression-list
|
427
|
+
(restrictions attached to argList pointers)
|
428
|
+
6) The number of restrictions
|
429
|
+
7) The number of locals vars reqd
|
430
|
+
8) The wildcard symbol (NULL if none)
|
431
|
+
9) Method actions
|
432
|
+
10) Method pretty-print form
|
433
|
+
11) A flag indicating whether to copy the
|
434
|
+
restriction types or just use the pointers
|
435
|
+
RETURNS : The new (old) method address
|
436
|
+
SIDE EFFECTS : Method added to (or changed in) method array for generic
|
437
|
+
Restrictions repacked into new method
|
438
|
+
Actions and pretty-print form attached
|
439
|
+
NOTES : Assumes if a method is being redefined, its busy
|
440
|
+
count is 0!!
|
441
|
+
IMPORTANT: Expects that FindMethodByRestrictions() has
|
442
|
+
previously been called to determine if this method
|
443
|
+
is already present or not. Arguments #1 and #2
|
444
|
+
should be the values obtained from FindMethod...().
|
445
|
+
************************************************************************/
|
446
|
+
Defmethod *AddMethod(
|
447
|
+
Environment *theEnv,
|
448
|
+
Defgeneric *gfunc,
|
449
|
+
Defmethod *meth,
|
450
|
+
int mposn,
|
451
|
+
unsigned short mi,
|
452
|
+
Expression *params,
|
453
|
+
unsigned short rcnt,
|
454
|
+
unsigned short lvars,
|
455
|
+
CLIPSLexeme *wildcard,
|
456
|
+
Expression *actions,
|
457
|
+
char *ppForm,
|
458
|
+
bool copyRestricts)
|
459
|
+
{
|
460
|
+
RESTRICTION *rptr, *rtmp;
|
461
|
+
int i,j;
|
462
|
+
unsigned short mai;
|
463
|
+
|
464
|
+
SaveBusyCount(gfunc);
|
465
|
+
if (meth == NULL)
|
466
|
+
{
|
467
|
+
mai = (mi != 0) ? FindMethodByIndex(gfunc,mi) : METHOD_NOT_FOUND;
|
468
|
+
if (mai == METHOD_NOT_FOUND)
|
469
|
+
meth = AddGenericMethod(theEnv,gfunc,mposn,mi);
|
470
|
+
else
|
471
|
+
{
|
472
|
+
DeleteMethodInfo(theEnv,gfunc,&gfunc->methods[mai]);
|
473
|
+
if (mai < mposn)
|
474
|
+
{
|
475
|
+
mposn--;
|
476
|
+
for (i = mai+1 ; i <= mposn ; i++)
|
477
|
+
GenCopyMemory(Defmethod,1,&gfunc->methods[i-1],&gfunc->methods[i]);
|
478
|
+
}
|
479
|
+
else
|
480
|
+
{
|
481
|
+
for (i = mai-1 ; i >= mposn ; i--)
|
482
|
+
GenCopyMemory(Defmethod,1,&gfunc->methods[i+1],&gfunc->methods[i]);
|
483
|
+
}
|
484
|
+
meth = &gfunc->methods[mposn];
|
485
|
+
meth->index = mi;
|
486
|
+
}
|
487
|
+
}
|
488
|
+
else
|
489
|
+
{
|
490
|
+
/* ================================
|
491
|
+
The old trace state is preserved
|
492
|
+
================================ */
|
493
|
+
ExpressionDeinstall(theEnv,meth->actions);
|
494
|
+
ReturnPackedExpression(theEnv,meth->actions);
|
495
|
+
if (meth->header.ppForm != NULL)
|
496
|
+
rm(theEnv,(void *) meth->header.ppForm,(sizeof(char) * (strlen(meth->header.ppForm)+1)));
|
497
|
+
}
|
498
|
+
meth->system = 0;
|
499
|
+
meth->actions = actions;
|
500
|
+
ExpressionInstall(theEnv,meth->actions);
|
501
|
+
meth->header.ppForm = ppForm;
|
502
|
+
if (mposn == -1)
|
503
|
+
{
|
504
|
+
RestoreBusyCount(gfunc);
|
505
|
+
return(meth);
|
506
|
+
}
|
507
|
+
|
508
|
+
meth->localVarCount = lvars;
|
509
|
+
meth->restrictionCount = rcnt;
|
510
|
+
|
511
|
+
if (wildcard != NULL)
|
512
|
+
{
|
513
|
+
if (rcnt == 0)
|
514
|
+
{ meth->minRestrictions = RESTRICTIONS_UNBOUNDED; }
|
515
|
+
else
|
516
|
+
{ meth->minRestrictions = rcnt - 1; }
|
517
|
+
meth->maxRestrictions = RESTRICTIONS_UNBOUNDED;
|
518
|
+
}
|
519
|
+
else
|
520
|
+
meth->minRestrictions = meth->maxRestrictions = rcnt;
|
521
|
+
if (rcnt != 0)
|
522
|
+
meth->restrictions = (RESTRICTION *)
|
523
|
+
gm2(theEnv,(sizeof(RESTRICTION) * rcnt));
|
524
|
+
else
|
525
|
+
meth->restrictions = NULL;
|
526
|
+
for (i = 0 ; i < rcnt ; i++)
|
527
|
+
{
|
528
|
+
rptr = &meth->restrictions[i];
|
529
|
+
rtmp = (RESTRICTION *) params->argList;
|
530
|
+
rptr->query = PackExpression(theEnv,rtmp->query);
|
531
|
+
rptr->tcnt = rtmp->tcnt;
|
532
|
+
if (copyRestricts)
|
533
|
+
{
|
534
|
+
if (rtmp->types != NULL)
|
535
|
+
{
|
536
|
+
rptr->types = (void **) gm2(theEnv,(rptr->tcnt * sizeof(void *)));
|
537
|
+
GenCopyMemory(void *,rptr->tcnt,rptr->types,rtmp->types);
|
538
|
+
}
|
539
|
+
else
|
540
|
+
rptr->types = NULL;
|
541
|
+
}
|
542
|
+
else
|
543
|
+
{
|
544
|
+
rptr->types = rtmp->types;
|
545
|
+
|
546
|
+
/* =====================================================
|
547
|
+
Make sure the types-array is not deallocated when the
|
548
|
+
temporary restriction nodes are
|
549
|
+
===================================================== */
|
550
|
+
rtmp->tcnt = 0;
|
551
|
+
rtmp->types = NULL;
|
552
|
+
}
|
553
|
+
ExpressionInstall(theEnv,rptr->query);
|
554
|
+
for (j = 0 ; j < rptr->tcnt ; j++)
|
555
|
+
#if OBJECT_SYSTEM
|
556
|
+
IncrementDefclassBusyCount(theEnv,(Defclass *) rptr->types[j]);
|
557
|
+
#else
|
558
|
+
IncrementIntegerCount((CLIPSInteger *) rptr->types[j]);
|
559
|
+
#endif
|
560
|
+
params = params->nextArg;
|
561
|
+
}
|
562
|
+
RestoreBusyCount(gfunc);
|
563
|
+
return(meth);
|
564
|
+
}
|
565
|
+
|
566
|
+
/*****************************************************
|
567
|
+
NAME : PackRestrictionTypes
|
568
|
+
DESCRIPTION : Takes the restriction type list
|
569
|
+
and packs it into a contiguous
|
570
|
+
array of void *.
|
571
|
+
INPUTS : 1) The restriction structure
|
572
|
+
2) The types expression list
|
573
|
+
RETURNS : Nothing useful
|
574
|
+
SIDE EFFECTS : Array allocated & expressions freed
|
575
|
+
NOTES : None
|
576
|
+
*****************************************************/
|
577
|
+
void PackRestrictionTypes(
|
578
|
+
Environment *theEnv,
|
579
|
+
RESTRICTION *rptr,
|
580
|
+
Expression *types)
|
581
|
+
{
|
582
|
+
Expression *tmp;
|
583
|
+
long i;
|
584
|
+
|
585
|
+
rptr->tcnt = 0;
|
586
|
+
for (tmp = types ; tmp != NULL ; tmp = tmp->nextArg)
|
587
|
+
rptr->tcnt++;
|
588
|
+
if (rptr->tcnt != 0)
|
589
|
+
rptr->types = (void **) gm2(theEnv,(sizeof(void *) * rptr->tcnt));
|
590
|
+
else
|
591
|
+
rptr->types = NULL;
|
592
|
+
for (i = 0 , tmp = types ; i < rptr->tcnt ; i++ , tmp = tmp->nextArg)
|
593
|
+
rptr->types[i] = tmp->value;
|
594
|
+
ReturnExpression(theEnv,types);
|
595
|
+
}
|
596
|
+
|
597
|
+
/***************************************************
|
598
|
+
NAME : DeleteTempRestricts
|
599
|
+
DESCRIPTION : Deallocates the method
|
600
|
+
temporary parameter list
|
601
|
+
INPUTS : The head of the list
|
602
|
+
RETURNS : Nothing useful
|
603
|
+
SIDE EFFECTS : List deallocated
|
604
|
+
NOTES : None
|
605
|
+
***************************************************/
|
606
|
+
void DeleteTempRestricts(
|
607
|
+
Environment *theEnv,
|
608
|
+
Expression *phead)
|
609
|
+
{
|
610
|
+
Expression *ptmp;
|
611
|
+
RESTRICTION *rtmp;
|
612
|
+
|
613
|
+
while (phead != NULL)
|
614
|
+
{
|
615
|
+
ptmp = phead;
|
616
|
+
phead = phead->nextArg;
|
617
|
+
rtmp = (RESTRICTION *) ptmp->argList;
|
618
|
+
rtn_struct(theEnv,expr,ptmp);
|
619
|
+
ReturnExpression(theEnv,rtmp->query);
|
620
|
+
if (rtmp->tcnt != 0)
|
621
|
+
rm(theEnv,rtmp->types,(sizeof(void *) * rtmp->tcnt));
|
622
|
+
rtn_struct(theEnv,restriction,rtmp);
|
623
|
+
}
|
624
|
+
}
|
625
|
+
|
626
|
+
/**********************************************************
|
627
|
+
NAME : FindMethodByRestrictions
|
628
|
+
DESCRIPTION : See if a method for the specified
|
629
|
+
generic satsifies the given restrictions
|
630
|
+
INPUTS : 1) Generic function
|
631
|
+
2) Parameter/restriction expression list
|
632
|
+
3) Number of restrictions
|
633
|
+
4) Wildcard symbol (can be NULL)
|
634
|
+
5) Caller's buffer for holding array posn
|
635
|
+
of where to add new generic method
|
636
|
+
(-1 if method already present)
|
637
|
+
RETURNS : The address of the found method, NULL if
|
638
|
+
not found
|
639
|
+
SIDE EFFECTS : Sets the caller's buffer to the index of
|
640
|
+
where to place the new method, -1 if
|
641
|
+
already present
|
642
|
+
NOTES : None
|
643
|
+
**********************************************************/
|
644
|
+
Defmethod *FindMethodByRestrictions(
|
645
|
+
Defgeneric *gfunc,
|
646
|
+
Expression *params,
|
647
|
+
int rcnt,
|
648
|
+
CLIPSLexeme *wildcard,
|
649
|
+
int *posn)
|
650
|
+
{
|
651
|
+
int i,cmp;
|
652
|
+
int min,max;
|
653
|
+
|
654
|
+
if (wildcard != NULL)
|
655
|
+
{
|
656
|
+
min = rcnt-1;
|
657
|
+
max = -1;
|
658
|
+
}
|
659
|
+
else
|
660
|
+
min = max = rcnt;
|
661
|
+
for (i = 0 ; i < gfunc->mcnt ; i++)
|
662
|
+
{
|
663
|
+
cmp = RestrictionsCompare(params,rcnt,min,max,&gfunc->methods[i]);
|
664
|
+
if (cmp == IDENTICAL)
|
665
|
+
{
|
666
|
+
*posn = -1;
|
667
|
+
return(&gfunc->methods[i]);
|
668
|
+
}
|
669
|
+
else if (cmp == HIGHER_PRECEDENCE)
|
670
|
+
{
|
671
|
+
*posn = i;
|
672
|
+
return NULL;
|
673
|
+
}
|
674
|
+
}
|
675
|
+
*posn = i;
|
676
|
+
return NULL;
|
677
|
+
}
|
678
|
+
|
679
|
+
/* =========================================
|
680
|
+
*****************************************
|
681
|
+
INTERNALLY VISIBLE FUNCTIONS
|
682
|
+
=========================================
|
683
|
+
***************************************** */
|
684
|
+
|
685
|
+
/***********************************************************
|
686
|
+
NAME : ValidGenericName
|
687
|
+
DESCRIPTION : Determines if a particular function name
|
688
|
+
can be overloaded
|
689
|
+
INPUTS : The name
|
690
|
+
RETURNS : True if OK, false otherwise
|
691
|
+
SIDE EFFECTS : Error message printed
|
692
|
+
NOTES : GetConstructNameAndComment() (called before
|
693
|
+
this function) ensures that the defgeneric
|
694
|
+
name does not conflict with one from
|
695
|
+
another module
|
696
|
+
***********************************************************/
|
697
|
+
static bool ValidGenericName(
|
698
|
+
Environment *theEnv,
|
699
|
+
const char *theDefgenericName)
|
700
|
+
{
|
701
|
+
Defgeneric *theDefgeneric;
|
702
|
+
#if DEFFUNCTION_CONSTRUCT
|
703
|
+
Defmodule *theModule;
|
704
|
+
Deffunction *theDeffunction;
|
705
|
+
#endif
|
706
|
+
struct functionDefinition *systemFunction;
|
707
|
+
|
708
|
+
/*==============================================*/
|
709
|
+
/* A defgeneric cannot be named the same as a */
|
710
|
+
/* construct type, e.g, defclass, defrule, etc. */
|
711
|
+
/*==============================================*/
|
712
|
+
|
713
|
+
if (FindConstruct(theEnv,theDefgenericName) != NULL)
|
714
|
+
{
|
715
|
+
PrintErrorID(theEnv,"GENRCPSR",3,false);
|
716
|
+
WriteString(theEnv,STDERR,"Defgenerics are not allowed to replace constructs.\n");
|
717
|
+
return false;
|
718
|
+
}
|
719
|
+
|
720
|
+
#if DEFFUNCTION_CONSTRUCT
|
721
|
+
/* ========================================
|
722
|
+
A defgeneric cannot be named the same as
|
723
|
+
a defffunction (either in this module or
|
724
|
+
imported from another)
|
725
|
+
======================================== */
|
726
|
+
theDeffunction = LookupDeffunctionInScope(theEnv,theDefgenericName);
|
727
|
+
if (theDeffunction != NULL)
|
728
|
+
{
|
729
|
+
theModule = GetConstructModuleItem(&theDeffunction->header)->theModule;
|
730
|
+
if (theModule != GetCurrentModule(theEnv))
|
731
|
+
{
|
732
|
+
PrintErrorID(theEnv,"GENRCPSR",4,false);
|
733
|
+
WriteString(theEnv,STDERR,"Deffunction '");
|
734
|
+
WriteString(theEnv,STDERR,DeffunctionName(theDeffunction));
|
735
|
+
WriteString(theEnv,STDERR,"' imported from module '");
|
736
|
+
WriteString(theEnv,STDERR,DefmoduleName(theModule));
|
737
|
+
WriteString(theEnv,STDERR,"' conflicts with this defgeneric.\n");
|
738
|
+
return false;
|
739
|
+
}
|
740
|
+
else
|
741
|
+
{
|
742
|
+
PrintErrorID(theEnv,"GENRCPSR",5,false);
|
743
|
+
WriteString(theEnv,STDERR,"Defgenerics are not allowed to replace deffunctions.\n");
|
744
|
+
}
|
745
|
+
return false;
|
746
|
+
}
|
747
|
+
#endif
|
748
|
+
|
749
|
+
/*===========================================*/
|
750
|
+
/* See if the defgeneric already exists in */
|
751
|
+
/* this module (or is imported from another) */
|
752
|
+
/*===========================================*/
|
753
|
+
|
754
|
+
theDefgeneric = FindDefgenericInModule(theEnv,theDefgenericName);
|
755
|
+
if (theDefgeneric != NULL)
|
756
|
+
{
|
757
|
+
/* ===========================================
|
758
|
+
And the redefinition of a defgeneric in
|
759
|
+
the current module is only valid if none
|
760
|
+
of its methods are executing
|
761
|
+
=========================================== */
|
762
|
+
if (MethodsExecuting(theDefgeneric))
|
763
|
+
{
|
764
|
+
MethodAlterError(theEnv,theDefgeneric);
|
765
|
+
return false;
|
766
|
+
}
|
767
|
+
}
|
768
|
+
|
769
|
+
/* =======================================
|
770
|
+
Only certain specific system functions
|
771
|
+
may be overloaded by generic functions
|
772
|
+
======================================= */
|
773
|
+
systemFunction = FindFunction(theEnv,theDefgenericName);
|
774
|
+
if ((systemFunction != NULL) ?
|
775
|
+
(systemFunction->overloadable == false) : false)
|
776
|
+
{
|
777
|
+
PrintErrorID(theEnv,"GENRCPSR",16,false);
|
778
|
+
WriteString(theEnv,STDERR,"The system function '");
|
779
|
+
WriteString(theEnv,STDERR,theDefgenericName);
|
780
|
+
WriteString(theEnv,STDERR,"' cannot be overloaded.\n");
|
781
|
+
return false;
|
782
|
+
}
|
783
|
+
return true;
|
784
|
+
}
|
785
|
+
|
786
|
+
#if DEBUGGING_FUNCTIONS
|
787
|
+
|
788
|
+
/***************************************************
|
789
|
+
NAME : CreateDefaultGenericPPForm
|
790
|
+
DESCRIPTION : Adds a default pretty-print form
|
791
|
+
for a gneric function when it is
|
792
|
+
impliciylt created by the defn
|
793
|
+
of its first method
|
794
|
+
INPUTS : The generic function
|
795
|
+
RETURNS : Nothing useful
|
796
|
+
SIDE EFFECTS : Pretty-print form created and
|
797
|
+
attached.
|
798
|
+
NOTES : None
|
799
|
+
***************************************************/
|
800
|
+
static void CreateDefaultGenericPPForm(
|
801
|
+
Environment *theEnv,
|
802
|
+
Defgeneric *gfunc)
|
803
|
+
{
|
804
|
+
const char *moduleName, *genericName;
|
805
|
+
char *buf;
|
806
|
+
|
807
|
+
moduleName = DefmoduleName(GetCurrentModule(theEnv));
|
808
|
+
genericName = DefgenericName(gfunc);
|
809
|
+
buf = (char *) gm2(theEnv,(sizeof(char) * (strlen(moduleName) + strlen(genericName) + 17)));
|
810
|
+
gensprintf(buf,"(defgeneric %s::%s)\n",moduleName,genericName);
|
811
|
+
SetDefgenericPPForm(theEnv,gfunc,buf);
|
812
|
+
}
|
813
|
+
|
814
|
+
#endif
|
815
|
+
|
816
|
+
/*******************************************************
|
817
|
+
NAME : ParseMethodNameAndIndex
|
818
|
+
DESCRIPTION : Parses the name of the method and
|
819
|
+
optional method index
|
820
|
+
INPUTS : 1) The logical name of the input source
|
821
|
+
2) Caller's buffer for method index
|
822
|
+
(0 if not specified)
|
823
|
+
RETURNS : The symbolic name of the method
|
824
|
+
SIDE EFFECTS : None
|
825
|
+
NOTES : Assumes "(defmethod " already parsed
|
826
|
+
*******************************************************/
|
827
|
+
static CLIPSLexeme *ParseMethodNameAndIndex(
|
828
|
+
Environment *theEnv,
|
829
|
+
const char *readSource,
|
830
|
+
unsigned short *theIndex,
|
831
|
+
struct token *genericInputToken)
|
832
|
+
{
|
833
|
+
CLIPSLexeme *gname;
|
834
|
+
|
835
|
+
*theIndex = 0;
|
836
|
+
gname = GetConstructNameAndComment(theEnv,readSource,genericInputToken,"defgeneric",
|
837
|
+
(FindConstructFunction *) FindDefgenericInModule,
|
838
|
+
NULL,"&",true,false,true,true);
|
839
|
+
if (gname == NULL)
|
840
|
+
return NULL;
|
841
|
+
if (genericInputToken->tknType == INTEGER_TOKEN)
|
842
|
+
{
|
843
|
+
unsigned short tmp;
|
844
|
+
|
845
|
+
PPBackup(theEnv);
|
846
|
+
PPBackup(theEnv);
|
847
|
+
SavePPBuffer(theEnv," ");
|
848
|
+
SavePPBuffer(theEnv,genericInputToken->printForm);
|
849
|
+
tmp = (unsigned short) genericInputToken->integerValue->contents;
|
850
|
+
if (tmp < 1)
|
851
|
+
{
|
852
|
+
PrintErrorID(theEnv,"GENRCPSR",6,false);
|
853
|
+
WriteString(theEnv,STDERR,"Method index out of range.\n");
|
854
|
+
return NULL;
|
855
|
+
}
|
856
|
+
*theIndex = tmp;
|
857
|
+
PPCRAndIndent(theEnv);
|
858
|
+
GetToken(theEnv,readSource,genericInputToken);
|
859
|
+
}
|
860
|
+
if (genericInputToken->tknType == STRING_TOKEN)
|
861
|
+
{
|
862
|
+
PPBackup(theEnv);
|
863
|
+
PPBackup(theEnv);
|
864
|
+
SavePPBuffer(theEnv," ");
|
865
|
+
SavePPBuffer(theEnv,genericInputToken->printForm);
|
866
|
+
PPCRAndIndent(theEnv);
|
867
|
+
GetToken(theEnv,readSource,genericInputToken);
|
868
|
+
}
|
869
|
+
return(gname);
|
870
|
+
}
|
871
|
+
|
872
|
+
/************************************************************************
|
873
|
+
NAME : ParseMethodParameters
|
874
|
+
DESCRIPTION : Parses method restrictions
|
875
|
+
(parameter names with class and expression specifiers)
|
876
|
+
INPUTS : 1) The logical name of the input source
|
877
|
+
2) Caller's buffer for the parameter name list
|
878
|
+
(Restriction structures are attached to
|
879
|
+
argList pointers of parameter nodes)
|
880
|
+
3) Caller's buffer for wildcard symbol (if any)
|
881
|
+
RETURNS : The number of parameters, or -1 on errors
|
882
|
+
SIDE EFFECTS : Memory allocated for parameters and restrictions
|
883
|
+
Parameter names stored in expression list
|
884
|
+
Parameter restrictions stored in contiguous array
|
885
|
+
NOTES : Any memory allocated is freed on errors
|
886
|
+
Assumes first opening parenthesis has been scanned
|
887
|
+
************************************************************************/
|
888
|
+
static unsigned short ParseMethodParameters(
|
889
|
+
Environment *theEnv,
|
890
|
+
const char *readSource,
|
891
|
+
Expression **params,
|
892
|
+
CLIPSLexeme **wildcard,
|
893
|
+
struct token *genericInputToken)
|
894
|
+
{
|
895
|
+
Expression *phead = NULL,*pprv;
|
896
|
+
CLIPSLexeme *pname;
|
897
|
+
RESTRICTION *rtmp;
|
898
|
+
unsigned short rcnt = 0;
|
899
|
+
|
900
|
+
*wildcard = NULL;
|
901
|
+
*params = NULL;
|
902
|
+
if (genericInputToken->tknType != LEFT_PARENTHESIS_TOKEN)
|
903
|
+
{
|
904
|
+
PrintErrorID(theEnv,"GENRCPSR",7,false);
|
905
|
+
WriteString(theEnv,STDERR,"Expected a '(' to begin method parameter restrictions.\n");
|
906
|
+
return PARAMETER_ERROR;
|
907
|
+
}
|
908
|
+
GetToken(theEnv,readSource,genericInputToken);
|
909
|
+
while (genericInputToken->tknType != RIGHT_PARENTHESIS_TOKEN)
|
910
|
+
{
|
911
|
+
if (*wildcard != NULL)
|
912
|
+
{
|
913
|
+
DeleteTempRestricts(theEnv,phead);
|
914
|
+
PrintErrorID(theEnv,"PRCCODE",8,false);
|
915
|
+
WriteString(theEnv,STDERR,"No parameters allowed after wildcard parameter.\n");
|
916
|
+
return PARAMETER_ERROR;
|
917
|
+
}
|
918
|
+
if ((genericInputToken->tknType == SF_VARIABLE_TOKEN) ||
|
919
|
+
(genericInputToken->tknType == MF_VARIABLE_TOKEN))
|
920
|
+
{
|
921
|
+
pname = genericInputToken->lexemeValue;
|
922
|
+
if (DuplicateParameters(theEnv,phead,&pprv,pname))
|
923
|
+
{
|
924
|
+
DeleteTempRestricts(theEnv,phead);
|
925
|
+
return PARAMETER_ERROR;
|
926
|
+
}
|
927
|
+
if (genericInputToken->tknType == MF_VARIABLE_TOKEN)
|
928
|
+
*wildcard = pname;
|
929
|
+
rtmp = get_struct(theEnv,restriction);
|
930
|
+
PackRestrictionTypes(theEnv,rtmp,NULL);
|
931
|
+
rtmp->query = NULL;
|
932
|
+
phead = AddParameter(theEnv,phead,pprv,pname,rtmp);
|
933
|
+
rcnt++;
|
934
|
+
}
|
935
|
+
else if (genericInputToken->tknType == LEFT_PARENTHESIS_TOKEN)
|
936
|
+
{
|
937
|
+
GetToken(theEnv,readSource,genericInputToken);
|
938
|
+
if ((genericInputToken->tknType != SF_VARIABLE_TOKEN) &&
|
939
|
+
(genericInputToken->tknType != MF_VARIABLE_TOKEN))
|
940
|
+
{
|
941
|
+
DeleteTempRestricts(theEnv,phead);
|
942
|
+
PrintErrorID(theEnv,"GENRCPSR",8,false);
|
943
|
+
WriteString(theEnv,STDERR,"Expected a variable for parameter specification.\n");
|
944
|
+
return PARAMETER_ERROR;
|
945
|
+
}
|
946
|
+
pname = genericInputToken->lexemeValue;
|
947
|
+
if (DuplicateParameters(theEnv,phead,&pprv,pname))
|
948
|
+
{
|
949
|
+
DeleteTempRestricts(theEnv,phead);
|
950
|
+
return PARAMETER_ERROR;
|
951
|
+
}
|
952
|
+
if (genericInputToken->tknType == MF_VARIABLE_TOKEN)
|
953
|
+
*wildcard = pname;
|
954
|
+
SavePPBuffer(theEnv," ");
|
955
|
+
rtmp = ParseRestriction(theEnv,readSource);
|
956
|
+
if (rtmp == NULL)
|
957
|
+
{
|
958
|
+
DeleteTempRestricts(theEnv,phead);
|
959
|
+
return PARAMETER_ERROR;
|
960
|
+
}
|
961
|
+
phead = AddParameter(theEnv,phead,pprv,pname,rtmp);
|
962
|
+
rcnt++;
|
963
|
+
}
|
964
|
+
else
|
965
|
+
{
|
966
|
+
DeleteTempRestricts(theEnv,phead);
|
967
|
+
PrintErrorID(theEnv,"GENRCPSR",9,false);
|
968
|
+
WriteString(theEnv,STDERR,"Expected a variable or '(' for parameter specification.\n");
|
969
|
+
return PARAMETER_ERROR;
|
970
|
+
}
|
971
|
+
PPCRAndIndent(theEnv);
|
972
|
+
GetToken(theEnv,readSource,genericInputToken);
|
973
|
+
}
|
974
|
+
if (rcnt != 0)
|
975
|
+
{
|
976
|
+
PPBackup(theEnv);
|
977
|
+
PPBackup(theEnv);
|
978
|
+
SavePPBuffer(theEnv,")");
|
979
|
+
}
|
980
|
+
*params = phead;
|
981
|
+
return(rcnt);
|
982
|
+
}
|
983
|
+
|
984
|
+
/************************************************************
|
985
|
+
NAME : ParseRestriction
|
986
|
+
DESCRIPTION : Parses the restriction for a parameter of a
|
987
|
+
method
|
988
|
+
This restriction is comprised of:
|
989
|
+
1) A list of classes (or types) that are
|
990
|
+
allowed for the parameter (None
|
991
|
+
if no type restriction)
|
992
|
+
2) And an optional restriction-query
|
993
|
+
expression
|
994
|
+
INPUTS : The logical name of the input source
|
995
|
+
RETURNS : The address of a RESTRICTION node, NULL on
|
996
|
+
errors
|
997
|
+
SIDE EFFECTS : RESTRICTION node allocated
|
998
|
+
Types are in a contiguous array of void *
|
999
|
+
Query is an expression
|
1000
|
+
NOTES : Assumes "(?<var> " has already been parsed
|
1001
|
+
H/L Syntax: <type>* [<query>])
|
1002
|
+
************************************************************/
|
1003
|
+
static RESTRICTION *ParseRestriction(
|
1004
|
+
Environment *theEnv,
|
1005
|
+
const char *readSource)
|
1006
|
+
{
|
1007
|
+
Expression *types = NULL,*new_types,
|
1008
|
+
*typesbot,*tmp,*tmp2,
|
1009
|
+
*query = NULL;
|
1010
|
+
RESTRICTION *rptr;
|
1011
|
+
struct token genericInputToken;
|
1012
|
+
|
1013
|
+
GetToken(theEnv,readSource,&genericInputToken);
|
1014
|
+
while (genericInputToken.tknType != RIGHT_PARENTHESIS_TOKEN)
|
1015
|
+
{
|
1016
|
+
if (query != NULL)
|
1017
|
+
{
|
1018
|
+
PrintErrorID(theEnv,"GENRCPSR",10,false);
|
1019
|
+
WriteString(theEnv,STDERR,"Query must be last in parameter restriction.\n");
|
1020
|
+
ReturnExpression(theEnv,query);
|
1021
|
+
ReturnExpression(theEnv,types);
|
1022
|
+
return NULL;
|
1023
|
+
}
|
1024
|
+
if (genericInputToken.tknType == SYMBOL_TOKEN)
|
1025
|
+
{
|
1026
|
+
new_types = ValidType(theEnv,genericInputToken.lexemeValue);
|
1027
|
+
if (new_types == NULL)
|
1028
|
+
{
|
1029
|
+
ReturnExpression(theEnv,types);
|
1030
|
+
ReturnExpression(theEnv,query);
|
1031
|
+
return NULL;
|
1032
|
+
}
|
1033
|
+
if (types == NULL)
|
1034
|
+
types = new_types;
|
1035
|
+
else
|
1036
|
+
{
|
1037
|
+
for (typesbot = tmp = types ; tmp != NULL ; tmp = tmp->nextArg)
|
1038
|
+
{
|
1039
|
+
for (tmp2 = new_types ; tmp2 != NULL ; tmp2 = tmp2->nextArg)
|
1040
|
+
{
|
1041
|
+
if (tmp->value == tmp2->value)
|
1042
|
+
{
|
1043
|
+
PrintErrorID(theEnv,"GENRCPSR",11,false);
|
1044
|
+
#if OBJECT_SYSTEM
|
1045
|
+
WriteString(theEnv,STDERR,"Duplicate classes not allowed in parameter restriction.\n");
|
1046
|
+
#else
|
1047
|
+
WriteString(theEnv,STDERR,"Duplicate types not allowed in parameter restriction.\n");
|
1048
|
+
#endif
|
1049
|
+
ReturnExpression(theEnv,query);
|
1050
|
+
ReturnExpression(theEnv,types);
|
1051
|
+
ReturnExpression(theEnv,new_types);
|
1052
|
+
return NULL;
|
1053
|
+
}
|
1054
|
+
if (RedundantClasses(theEnv,tmp->value,tmp2->value))
|
1055
|
+
{
|
1056
|
+
ReturnExpression(theEnv,query);
|
1057
|
+
ReturnExpression(theEnv,types);
|
1058
|
+
ReturnExpression(theEnv,new_types);
|
1059
|
+
return NULL;
|
1060
|
+
}
|
1061
|
+
}
|
1062
|
+
typesbot = tmp;
|
1063
|
+
}
|
1064
|
+
typesbot->nextArg = new_types;
|
1065
|
+
}
|
1066
|
+
}
|
1067
|
+
else if (genericInputToken.tknType == LEFT_PARENTHESIS_TOKEN)
|
1068
|
+
{
|
1069
|
+
query = Function1Parse(theEnv,readSource);
|
1070
|
+
if (query == NULL)
|
1071
|
+
{
|
1072
|
+
ReturnExpression(theEnv,types);
|
1073
|
+
return NULL;
|
1074
|
+
}
|
1075
|
+
if (GetParsedBindNames(theEnv) != NULL)
|
1076
|
+
{
|
1077
|
+
PrintErrorID(theEnv,"GENRCPSR",12,false);
|
1078
|
+
WriteString(theEnv,STDERR,"Binds are not allowed in query expressions.\n");
|
1079
|
+
ReturnExpression(theEnv,query);
|
1080
|
+
ReturnExpression(theEnv,types);
|
1081
|
+
return NULL;
|
1082
|
+
}
|
1083
|
+
}
|
1084
|
+
#if DEFGLOBAL_CONSTRUCT
|
1085
|
+
else if (genericInputToken.tknType == GBL_VARIABLE_TOKEN)
|
1086
|
+
query = GenConstant(theEnv,GBL_VARIABLE,genericInputToken.value);
|
1087
|
+
#endif
|
1088
|
+
else
|
1089
|
+
{
|
1090
|
+
PrintErrorID(theEnv,"GENRCPSR",13,false);
|
1091
|
+
#if OBJECT_SYSTEM
|
1092
|
+
WriteString(theEnv,STDERR,"Expected a valid class name or query.\n");
|
1093
|
+
#else
|
1094
|
+
WriteString(theEnv,STDERR,"Expected a valid type name or query.\n");
|
1095
|
+
#endif
|
1096
|
+
ReturnExpression(theEnv,query);
|
1097
|
+
ReturnExpression(theEnv,types);
|
1098
|
+
return NULL;
|
1099
|
+
}
|
1100
|
+
SavePPBuffer(theEnv," ");
|
1101
|
+
GetToken(theEnv,readSource,&genericInputToken);
|
1102
|
+
}
|
1103
|
+
PPBackup(theEnv);
|
1104
|
+
PPBackup(theEnv);
|
1105
|
+
SavePPBuffer(theEnv,")");
|
1106
|
+
if ((types == NULL) && (query == NULL))
|
1107
|
+
{
|
1108
|
+
PrintErrorID(theEnv,"GENRCPSR",13,false);
|
1109
|
+
#if OBJECT_SYSTEM
|
1110
|
+
WriteString(theEnv,STDERR,"Expected a valid class name or query.\n");
|
1111
|
+
#else
|
1112
|
+
WriteString(theEnv,STDERR,"Expected a valid type name or query.\n");
|
1113
|
+
#endif
|
1114
|
+
return NULL;
|
1115
|
+
}
|
1116
|
+
rptr = get_struct(theEnv,restriction);
|
1117
|
+
rptr->query = query;
|
1118
|
+
PackRestrictionTypes(theEnv,rptr,types);
|
1119
|
+
return(rptr);
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
/*****************************************************************
|
1123
|
+
NAME : ReplaceCurrentArgRefs
|
1124
|
+
DESCRIPTION : Replaces all references to ?current-argument in
|
1125
|
+
method parameter queries with special calls
|
1126
|
+
to (gnrc-current-arg)
|
1127
|
+
INPUTS : The query expression
|
1128
|
+
RETURNS : Nothing useful
|
1129
|
+
SIDE EFFECTS : Variable references to ?current-argument replaced
|
1130
|
+
NOTES : None
|
1131
|
+
*****************************************************************/
|
1132
|
+
static void ReplaceCurrentArgRefs(
|
1133
|
+
Environment *theEnv,
|
1134
|
+
Expression *query)
|
1135
|
+
{
|
1136
|
+
while (query != NULL)
|
1137
|
+
{
|
1138
|
+
if ((query->type != SF_VARIABLE) ? false :
|
1139
|
+
(strcmp(query->lexemeValue->contents,CURR_ARG_VAR) == 0))
|
1140
|
+
{
|
1141
|
+
query->type = FCALL;
|
1142
|
+
query->value = FindFunction(theEnv,"(gnrc-current-arg)");
|
1143
|
+
}
|
1144
|
+
if (query->argList != NULL)
|
1145
|
+
ReplaceCurrentArgRefs(theEnv,query->argList);
|
1146
|
+
query = query->nextArg;
|
1147
|
+
}
|
1148
|
+
}
|
1149
|
+
|
1150
|
+
/**********************************************************
|
1151
|
+
NAME : DuplicateParameters
|
1152
|
+
DESCRIPTION : Examines the parameter expression
|
1153
|
+
chain for a method looking duplicates.
|
1154
|
+
INPUTS : 1) The parameter chain (can be NULL)
|
1155
|
+
2) Caller's buffer for address of
|
1156
|
+
last node searched (can be used to
|
1157
|
+
later attach new parameter)
|
1158
|
+
3) The name of the parameter being checked
|
1159
|
+
RETURNS : True if duplicates found, false otherwise
|
1160
|
+
SIDE EFFECTS : Caller's prv address set
|
1161
|
+
NOTES : Assumes all parameter list nodes are WORDS
|
1162
|
+
**********************************************************/
|
1163
|
+
static bool DuplicateParameters(
|
1164
|
+
Environment *theEnv,
|
1165
|
+
Expression *head,
|
1166
|
+
Expression **prv,
|
1167
|
+
CLIPSLexeme *name)
|
1168
|
+
{
|
1169
|
+
*prv = NULL;
|
1170
|
+
while (head != NULL)
|
1171
|
+
{
|
1172
|
+
if (head->value == (void *) name)
|
1173
|
+
{
|
1174
|
+
PrintErrorID(theEnv,"PRCCODE",7,false);
|
1175
|
+
WriteString(theEnv,STDERR,"Duplicate parameter names not allowed.\n");
|
1176
|
+
return true;
|
1177
|
+
}
|
1178
|
+
*prv = head;
|
1179
|
+
head = head->nextArg;
|
1180
|
+
}
|
1181
|
+
return false;
|
1182
|
+
}
|
1183
|
+
|
1184
|
+
/*****************************************************************
|
1185
|
+
NAME : AddParameter
|
1186
|
+
DESCRIPTION : Shoves a new paramter with its restriction
|
1187
|
+
onto the list for a method
|
1188
|
+
The parameter list is a list of expressions
|
1189
|
+
linked by neext_arg pointers, and the
|
1190
|
+
argList pointers are used for the restrictions
|
1191
|
+
INPUTS : 1) The head of the list
|
1192
|
+
2) The bottom of the list
|
1193
|
+
3) The parameter name
|
1194
|
+
4) The parameter restriction
|
1195
|
+
RETURNS : The (new) head of the list
|
1196
|
+
SIDE EFFECTS : New parameter expression node allocated, set,
|
1197
|
+
and attached
|
1198
|
+
NOTES : None
|
1199
|
+
*****************************************************************/
|
1200
|
+
static Expression *AddParameter(
|
1201
|
+
Environment *theEnv,
|
1202
|
+
Expression *phead,
|
1203
|
+
Expression *pprv,
|
1204
|
+
CLIPSLexeme *pname,
|
1205
|
+
RESTRICTION *rptr)
|
1206
|
+
{
|
1207
|
+
Expression *ptmp;
|
1208
|
+
|
1209
|
+
ptmp = GenConstant(theEnv,SYMBOL_TYPE,pname);
|
1210
|
+
if (phead == NULL)
|
1211
|
+
phead = ptmp;
|
1212
|
+
else
|
1213
|
+
pprv->nextArg = ptmp;
|
1214
|
+
ptmp->argList = (Expression *) rptr;
|
1215
|
+
return(phead);
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
/**************************************************************
|
1219
|
+
NAME : ValidType
|
1220
|
+
DESCRIPTION : Examines the name of a restriction type and
|
1221
|
+
forms a list of integer-code expressions
|
1222
|
+
corresponding to the primitive types
|
1223
|
+
(or a Class address if COOL is installed)
|
1224
|
+
INPUTS : The type name
|
1225
|
+
RETURNS : The expression chain (NULL on errors)
|
1226
|
+
SIDE EFFECTS : Expression type chain allocated
|
1227
|
+
one or more nodes holding codes for types
|
1228
|
+
(or class addresses)
|
1229
|
+
NOTES : None
|
1230
|
+
*************************************************************/
|
1231
|
+
static Expression *ValidType(
|
1232
|
+
Environment *theEnv,
|
1233
|
+
CLIPSLexeme *tname)
|
1234
|
+
{
|
1235
|
+
#if OBJECT_SYSTEM
|
1236
|
+
Defclass *cls;
|
1237
|
+
|
1238
|
+
if (FindModuleSeparator(tname->contents))
|
1239
|
+
IllegalModuleSpecifierMessage(theEnv);
|
1240
|
+
else
|
1241
|
+
{
|
1242
|
+
cls = LookupDefclassInScope(theEnv,tname->contents);
|
1243
|
+
if (cls == NULL)
|
1244
|
+
{
|
1245
|
+
PrintErrorID(theEnv,"GENRCPSR",14,false);
|
1246
|
+
WriteString(theEnv,STDERR,"Unknown class in method.\n");
|
1247
|
+
return NULL;
|
1248
|
+
}
|
1249
|
+
return(GenConstant(theEnv,DEFCLASS_PTR,cls));
|
1250
|
+
}
|
1251
|
+
#else
|
1252
|
+
if (strcmp(tname->contents,INTEGER_TYPE_NAME) == 0)
|
1253
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,INTEGER_TYPE)));
|
1254
|
+
if (strcmp(tname->contents,FLOAT_TYPE_NAME) == 0)
|
1255
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,FLOAT_TYPE)));
|
1256
|
+
if (strcmp(tname->contents,SYMBOL_TYPE_NAME) == 0)
|
1257
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,SYMBOL_TYPE)));
|
1258
|
+
if (strcmp(tname->contents,STRING_TYPE_NAME) == 0)
|
1259
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,STRING_TYPE)));
|
1260
|
+
if (strcmp(tname->contents,MULTIFIELD_TYPE_NAME) == 0)
|
1261
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,MULTIFIELD_TYPE)));
|
1262
|
+
if (strcmp(tname->contents,EXTERNAL_ADDRESS_TYPE_NAME) == 0)
|
1263
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,EXTERNAL_ADDRESS_TYPE)));
|
1264
|
+
if (strcmp(tname->contents,FACT_ADDRESS_TYPE_NAME) == 0)
|
1265
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,FACT_ADDRESS_TYPE)));
|
1266
|
+
if (strcmp(tname->contents,NUMBER_TYPE_NAME) == 0)
|
1267
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,NUMBER_TYPE_CODE)));
|
1268
|
+
if (strcmp(tname->contents,LEXEME_TYPE_NAME) == 0)
|
1269
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,LEXEME_TYPE_CODE)));
|
1270
|
+
if (strcmp(tname->contents,ADDRESS_TYPE_NAME) == 0)
|
1271
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,ADDRESS_TYPE_CODE)));
|
1272
|
+
if (strcmp(tname->contents,PRIMITIVE_TYPE_NAME) == 0)
|
1273
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,PRIMITIVE_TYPE_CODE)));
|
1274
|
+
if (strcmp(tname->contents,OBJECT_TYPE_NAME) == 0)
|
1275
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,OBJECT_TYPE_CODE)));
|
1276
|
+
if (strcmp(tname->contents,INSTANCE_TYPE_NAME) == 0)
|
1277
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,INSTANCE_TYPE_CODE)));
|
1278
|
+
if (strcmp(tname->contents,INSTANCE_NAME_TYPE_NAME) == 0)
|
1279
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,INSTANCE_NAME_TYPE)));
|
1280
|
+
if (strcmp(tname->contents,INSTANCE_ADDRESS_TYPE_NAME) == 0)
|
1281
|
+
return(GenConstant(theEnv,INTEGER_TYPE,CreateInteger(theEnv,INSTANCE_ADDRESS_TYPE)));
|
1282
|
+
|
1283
|
+
PrintErrorID(theEnv,"GENRCPSR",14,false);
|
1284
|
+
WriteString(theEnv,STDERR,"Unknown type in method.\n");
|
1285
|
+
#endif
|
1286
|
+
return NULL;
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
/*************************************************************
|
1290
|
+
NAME : RedundantClasses
|
1291
|
+
DESCRIPTION : Determines if one class (type) is
|
1292
|
+
subsumes (or is subsumed by) another.
|
1293
|
+
INPUTS : Two void pointers which are class pointers
|
1294
|
+
if COOL is installed or integer hash nodes
|
1295
|
+
for type codes otherwise.
|
1296
|
+
RETURNS : True if there is subsumption, false otherwise
|
1297
|
+
SIDE EFFECTS : An error message is printed, if appropriate.
|
1298
|
+
NOTES : None
|
1299
|
+
*************************************************************/
|
1300
|
+
static bool RedundantClasses(
|
1301
|
+
Environment *theEnv,
|
1302
|
+
void *c1,
|
1303
|
+
void *c2)
|
1304
|
+
{
|
1305
|
+
const char *tname;
|
1306
|
+
|
1307
|
+
#if OBJECT_SYSTEM
|
1308
|
+
if (HasSuperclass((Defclass *) c1,(Defclass *) c2))
|
1309
|
+
tname = DefclassName((Defclass *) c1);
|
1310
|
+
else if (HasSuperclass((Defclass *) c2,(Defclass *) c1))
|
1311
|
+
tname = DefclassName((Defclass *) c2);
|
1312
|
+
#else
|
1313
|
+
if (SubsumeType(((CLIPSInteger *) c1)->contents,((CLIPSInteger *) c2)->contents))
|
1314
|
+
tname = TypeName(theEnv,((CLIPSInteger *) c1)->contents);
|
1315
|
+
else if (SubsumeType(((CLIPSInteger *) c2)->contents,((CLIPSInteger *) c1)->contents))
|
1316
|
+
tname = TypeName(theEnv,((CLIPSInteger *) c2)->contents);
|
1317
|
+
#endif
|
1318
|
+
else
|
1319
|
+
return false;
|
1320
|
+
PrintErrorID(theEnv,"GENRCPSR",15,false);
|
1321
|
+
WriteString(theEnv,STDERR,"Class '");
|
1322
|
+
WriteString(theEnv,STDERR,tname);
|
1323
|
+
WriteString(theEnv,STDERR,"' is redundant.\n");
|
1324
|
+
return true;
|
1325
|
+
}
|
1326
|
+
|
1327
|
+
/*********************************************************
|
1328
|
+
NAME : AddGeneric
|
1329
|
+
DESCRIPTION : Inserts a new generic function
|
1330
|
+
header into the generic list
|
1331
|
+
INPUTS : 1) Symbolic name of the new generic
|
1332
|
+
2) Caller's input buffer for flag
|
1333
|
+
if added generic is new or not
|
1334
|
+
RETURNS : The address of the new node, or
|
1335
|
+
address of old node if already present
|
1336
|
+
SIDE EFFECTS : Generic header inserted
|
1337
|
+
If the node is already present, it is
|
1338
|
+
moved to the end of the list, otherwise
|
1339
|
+
the new node is inserted at the end
|
1340
|
+
NOTES : None
|
1341
|
+
*********************************************************/
|
1342
|
+
static Defgeneric *AddGeneric(
|
1343
|
+
Environment *theEnv,
|
1344
|
+
CLIPSLexeme *name,
|
1345
|
+
bool *newGeneric)
|
1346
|
+
{
|
1347
|
+
Defgeneric *gfunc;
|
1348
|
+
|
1349
|
+
gfunc = FindDefgenericInModule(theEnv,name->contents);
|
1350
|
+
if (gfunc != NULL)
|
1351
|
+
{
|
1352
|
+
*newGeneric = false;
|
1353
|
+
|
1354
|
+
if (ConstructData(theEnv)->CheckSyntaxMode)
|
1355
|
+
{ return(gfunc); }
|
1356
|
+
|
1357
|
+
/* ================================
|
1358
|
+
The old trace state is preserved
|
1359
|
+
================================ */
|
1360
|
+
RemoveConstructFromModule(theEnv,&gfunc->header);
|
1361
|
+
}
|
1362
|
+
else
|
1363
|
+
{
|
1364
|
+
*newGeneric = true;
|
1365
|
+
gfunc = NewGeneric(theEnv,name);
|
1366
|
+
IncrementLexemeCount(name);
|
1367
|
+
AddImplicitMethods(theEnv,gfunc);
|
1368
|
+
}
|
1369
|
+
AddConstructToModule(&gfunc->header);
|
1370
|
+
return(gfunc);
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
/**********************************************************************
|
1374
|
+
NAME : AddGenericMethod
|
1375
|
+
DESCRIPTION : Inserts a blank method (with the method-index set)
|
1376
|
+
into the specified position of the generic
|
1377
|
+
method array
|
1378
|
+
INPUTS : 1) The generic function
|
1379
|
+
2) The index where to add the method in the array
|
1380
|
+
3) The method user-index (0 if don't care)
|
1381
|
+
RETURNS : The address of the new method
|
1382
|
+
SIDE EFFECTS : Fields initialized (index set) and new method inserted
|
1383
|
+
Generic function new method-index set to specified
|
1384
|
+
by user-index if > current new method-index
|
1385
|
+
NOTES : None
|
1386
|
+
**********************************************************************/
|
1387
|
+
static Defmethod *AddGenericMethod(
|
1388
|
+
Environment *theEnv,
|
1389
|
+
Defgeneric *gfunc,
|
1390
|
+
int mposn,
|
1391
|
+
unsigned short mi)
|
1392
|
+
{
|
1393
|
+
Defmethod *narr;
|
1394
|
+
long b, e;
|
1395
|
+
|
1396
|
+
narr = (Defmethod *) gm2(theEnv,(sizeof(Defmethod) * (gfunc->mcnt+1)));
|
1397
|
+
for (b = e = 0 ; b < gfunc->mcnt ; b++ , e++)
|
1398
|
+
{
|
1399
|
+
if (b == mposn)
|
1400
|
+
e++;
|
1401
|
+
GenCopyMemory(Defmethod,1,&narr[e],&gfunc->methods[b]);
|
1402
|
+
}
|
1403
|
+
if (mi == 0)
|
1404
|
+
narr[mposn].index = gfunc->new_index++;
|
1405
|
+
else
|
1406
|
+
{
|
1407
|
+
narr[mposn].index = mi;
|
1408
|
+
if (mi >= gfunc->new_index)
|
1409
|
+
gfunc->new_index = mi + 1;
|
1410
|
+
}
|
1411
|
+
narr[mposn].busy = 0;
|
1412
|
+
#if DEBUGGING_FUNCTIONS
|
1413
|
+
narr[mposn].trace = DefgenericData(theEnv)->WatchMethods;
|
1414
|
+
#endif
|
1415
|
+
narr[mposn].minRestrictions = 0;
|
1416
|
+
narr[mposn].maxRestrictions = 0;
|
1417
|
+
narr[mposn].restrictionCount = 0;
|
1418
|
+
narr[mposn].localVarCount = 0;
|
1419
|
+
narr[mposn].system = 0;
|
1420
|
+
narr[mposn].restrictions = NULL;
|
1421
|
+
narr[mposn].actions = NULL;
|
1422
|
+
narr[mposn].header.name = NULL;
|
1423
|
+
narr[mposn].header.next = NULL;
|
1424
|
+
narr[mposn].header.constructType = DEFMETHOD;
|
1425
|
+
narr[mposn].header.env = theEnv;
|
1426
|
+
narr[mposn].header.whichModule = gfunc->header.whichModule;
|
1427
|
+
narr[mposn].header.ppForm = NULL;
|
1428
|
+
narr[mposn].header.usrData = NULL;
|
1429
|
+
|
1430
|
+
if (gfunc->mcnt != 0)
|
1431
|
+
rm(theEnv,gfunc->methods,(sizeof(Defmethod) * gfunc->mcnt));
|
1432
|
+
gfunc->mcnt++;
|
1433
|
+
gfunc->methods = narr;
|
1434
|
+
return(&narr[mposn]);
|
1435
|
+
}
|
1436
|
+
|
1437
|
+
/****************************************************************
|
1438
|
+
NAME : RestrictionsCompare
|
1439
|
+
DESCRIPTION : Compares the restriction-expression list
|
1440
|
+
with an existing methods restrictions to
|
1441
|
+
determine an ordering
|
1442
|
+
INPUTS : 1) The parameter/restriction expression list
|
1443
|
+
2) The total number of restrictions
|
1444
|
+
3) The number of minimum restrictions
|
1445
|
+
4) The number of maximum restrictions (-1
|
1446
|
+
if unlimited)
|
1447
|
+
5) The method with which to compare restrictions
|
1448
|
+
RETURNS : A code representing how the method restrictions
|
1449
|
+
-1 : New restrictions have higher precedence
|
1450
|
+
0 : New restrictions are identical
|
1451
|
+
1 : New restrictions have lower precedence
|
1452
|
+
SIDE EFFECTS : None
|
1453
|
+
NOTES : The new restrictions are stored in the argList
|
1454
|
+
pointers of the parameter expressions
|
1455
|
+
****************************************************************/
|
1456
|
+
static int RestrictionsCompare(
|
1457
|
+
Expression *params,
|
1458
|
+
int rcnt,
|
1459
|
+
int min,
|
1460
|
+
int max,
|
1461
|
+
Defmethod *meth)
|
1462
|
+
{
|
1463
|
+
int i;
|
1464
|
+
RESTRICTION *r1,*r2;
|
1465
|
+
bool diff = false;
|
1466
|
+
int rtn;
|
1467
|
+
|
1468
|
+
for (i = 0 ; (i < rcnt) && (i < meth->restrictionCount) ; i++)
|
1469
|
+
{
|
1470
|
+
/* =============================================================
|
1471
|
+
A wildcard parameter always has lower precedence than
|
1472
|
+
a regular parameter, regardless of the class restriction list
|
1473
|
+
============================================================= */
|
1474
|
+
if ((i == rcnt-1) && (max == -1) &&
|
1475
|
+
(meth->maxRestrictions != RESTRICTIONS_UNBOUNDED))
|
1476
|
+
return LOWER_PRECEDENCE;
|
1477
|
+
if ((i == meth->restrictionCount-1) && (max != -1) &&
|
1478
|
+
(meth->maxRestrictions == RESTRICTIONS_UNBOUNDED))
|
1479
|
+
return HIGHER_PRECEDENCE;
|
1480
|
+
|
1481
|
+
/* =============================================================
|
1482
|
+
The parameter with the most specific type list has precedence
|
1483
|
+
============================================================= */
|
1484
|
+
r1 = (RESTRICTION *) params->argList;
|
1485
|
+
r2 = &meth->restrictions[i];
|
1486
|
+
rtn = TypeListCompare(r1,r2);
|
1487
|
+
if (rtn != IDENTICAL)
|
1488
|
+
return rtn;
|
1489
|
+
|
1490
|
+
/* =====================================================
|
1491
|
+
The parameter with a query restriction has precedence
|
1492
|
+
===================================================== */
|
1493
|
+
if ((r1->query == NULL) && (r2->query != NULL))
|
1494
|
+
return LOWER_PRECEDENCE;
|
1495
|
+
if ((r1->query != NULL) && (r2->query == NULL))
|
1496
|
+
return HIGHER_PRECEDENCE;
|
1497
|
+
|
1498
|
+
/* ==========================================================
|
1499
|
+
Remember if the method restrictions differ at all - query
|
1500
|
+
expressions must be identical as well for the restrictions
|
1501
|
+
to be the same
|
1502
|
+
========================================================== */
|
1503
|
+
if (IdenticalExpression(r1->query,r2->query) == false)
|
1504
|
+
diff = true;
|
1505
|
+
params = params->nextArg;
|
1506
|
+
}
|
1507
|
+
|
1508
|
+
/* =============================================================
|
1509
|
+
If the methods have the same number of parameters here, they
|
1510
|
+
are either the same restrictions, or they differ only in
|
1511
|
+
the query restrictions
|
1512
|
+
============================================================= */
|
1513
|
+
if (rcnt == meth->restrictionCount)
|
1514
|
+
return(diff ? LOWER_PRECEDENCE : IDENTICAL);
|
1515
|
+
|
1516
|
+
/* =============================================
|
1517
|
+
The method with the greater number of regular
|
1518
|
+
parameters has precedence
|
1519
|
+
|
1520
|
+
If they require the smae # of reg params,
|
1521
|
+
then one without a wildcard has precedence
|
1522
|
+
============================================= */
|
1523
|
+
if (min > meth->minRestrictions)
|
1524
|
+
return HIGHER_PRECEDENCE;
|
1525
|
+
if (meth->minRestrictions < min)
|
1526
|
+
return LOWER_PRECEDENCE;
|
1527
|
+
return((max == - 1) ? LOWER_PRECEDENCE : HIGHER_PRECEDENCE);
|
1528
|
+
}
|
1529
|
+
|
1530
|
+
/*****************************************************
|
1531
|
+
NAME : TypeListCompare
|
1532
|
+
DESCRIPTION : Determines the precedence between
|
1533
|
+
the class lists on two restrictions
|
1534
|
+
INPUTS : 1) Restriction address #1
|
1535
|
+
2) Restriction address #2
|
1536
|
+
RETURNS : -1 : r1 precedes r2
|
1537
|
+
0 : Identical classes
|
1538
|
+
1 : r2 precedes r1
|
1539
|
+
SIDE EFFECTS : None
|
1540
|
+
NOTES : None
|
1541
|
+
*****************************************************/
|
1542
|
+
static int TypeListCompare(
|
1543
|
+
RESTRICTION *r1,
|
1544
|
+
RESTRICTION *r2)
|
1545
|
+
{
|
1546
|
+
long i;
|
1547
|
+
bool diff = false;
|
1548
|
+
|
1549
|
+
if ((r1->tcnt == 0) && (r2->tcnt == 0))
|
1550
|
+
return(IDENTICAL);
|
1551
|
+
if (r1->tcnt == 0)
|
1552
|
+
return(LOWER_PRECEDENCE);
|
1553
|
+
if (r2->tcnt == 0)
|
1554
|
+
return(HIGHER_PRECEDENCE);
|
1555
|
+
for (i = 0 ; (i < r1->tcnt) && (i < r2->tcnt) ; i++)
|
1556
|
+
{
|
1557
|
+
if (r1->types[i] != r2->types[i])
|
1558
|
+
{
|
1559
|
+
diff = true;
|
1560
|
+
#if OBJECT_SYSTEM
|
1561
|
+
if (HasSuperclass((Defclass *) r1->types[i],(Defclass *) r2->types[i]))
|
1562
|
+
return(HIGHER_PRECEDENCE);
|
1563
|
+
if (HasSuperclass((Defclass *) r2->types[i],(Defclass *) r1->types[i]))
|
1564
|
+
return(LOWER_PRECEDENCE);
|
1565
|
+
#else
|
1566
|
+
if (SubsumeType(((CLIPSInteger *) r1->types[i])->contents,((CLIPSInteger *) r2->types[i])->contents))
|
1567
|
+
return(HIGHER_PRECEDENCE);
|
1568
|
+
if (SubsumeType(((CLIPSInteger *) r2->types[i])->contents,((CLIPSInteger *) r1->types[i])->contents))
|
1569
|
+
return(LOWER_PRECEDENCE);
|
1570
|
+
#endif
|
1571
|
+
}
|
1572
|
+
}
|
1573
|
+
if (r1->tcnt < r2->tcnt)
|
1574
|
+
return(HIGHER_PRECEDENCE);
|
1575
|
+
if (r1->tcnt > r2->tcnt)
|
1576
|
+
return(LOWER_PRECEDENCE);
|
1577
|
+
if (diff)
|
1578
|
+
return(LOWER_PRECEDENCE);
|
1579
|
+
return(IDENTICAL);
|
1580
|
+
}
|
1581
|
+
|
1582
|
+
/***************************************************
|
1583
|
+
NAME : NewGeneric
|
1584
|
+
DESCRIPTION : Allocates and initializes a new
|
1585
|
+
generic function header
|
1586
|
+
INPUTS : The name of the new generic
|
1587
|
+
RETURNS : The address of the new generic
|
1588
|
+
SIDE EFFECTS : Generic function header created
|
1589
|
+
NOTES : None
|
1590
|
+
***************************************************/
|
1591
|
+
static Defgeneric *NewGeneric(
|
1592
|
+
Environment *theEnv,
|
1593
|
+
CLIPSLexeme *gname)
|
1594
|
+
{
|
1595
|
+
Defgeneric *ngen;
|
1596
|
+
|
1597
|
+
ngen = get_struct(theEnv,defgeneric);
|
1598
|
+
InitializeConstructHeader(theEnv,"defgeneric",DEFGENERIC,&ngen->header,gname);
|
1599
|
+
ngen->busy = 0;
|
1600
|
+
ngen->new_index = 1;
|
1601
|
+
ngen->methods = NULL;
|
1602
|
+
ngen->mcnt = 0;
|
1603
|
+
#if DEBUGGING_FUNCTIONS
|
1604
|
+
ngen->trace = DefgenericData(theEnv)->WatchGenerics;
|
1605
|
+
#endif
|
1606
|
+
return(ngen);
|
1607
|
+
}
|
1608
|
+
|
1609
|
+
#endif /* DEFGENERIC_CONSTRUCT && (! BLOAD_ONLY) && (! RUN_TIME) */
|
1610
|
+
|
1611
|
+
/***************************************************
|
1612
|
+
NAME :
|
1613
|
+
DESCRIPTION :
|
1614
|
+
INPUTS :
|
1615
|
+
RETURNS :
|
1616
|
+
SIDE EFFECTS :
|
1617
|
+
NOTES :
|
1618
|
+
***************************************************/
|