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,850 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.40 07/30/16 */
|
5
|
+
/* */
|
6
|
+
/* MULTIPLE INHERITANCE PARSER MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: Parsing Routines for Multiple Inheritance */
|
11
|
+
/* */
|
12
|
+
/* Principal Programmer(s): */
|
13
|
+
/* Brian L. Dantes */
|
14
|
+
/* */
|
15
|
+
/* Contributing Programmer(s): */
|
16
|
+
/* */
|
17
|
+
/* Revision History: */
|
18
|
+
/* */
|
19
|
+
/* 6.30: Changed integer type/precision. */
|
20
|
+
/* */
|
21
|
+
/* Added const qualifiers to remove C++ */
|
22
|
+
/* deprecation warnings. */
|
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
|
+
/*************************************************************/
|
32
|
+
|
33
|
+
/* =========================================
|
34
|
+
*****************************************
|
35
|
+
EXTERNAL DEFINITIONS
|
36
|
+
=========================================
|
37
|
+
***************************************** */
|
38
|
+
#include "setup.h"
|
39
|
+
|
40
|
+
#if OBJECT_SYSTEM && (! BLOAD_ONLY) && (! RUN_TIME)
|
41
|
+
|
42
|
+
#include "classcom.h"
|
43
|
+
#include "classfun.h"
|
44
|
+
#include "envrnmnt.h"
|
45
|
+
#include "memalloc.h"
|
46
|
+
#include "modulutl.h"
|
47
|
+
#include "pprint.h"
|
48
|
+
#include "prntutil.h"
|
49
|
+
#include "router.h"
|
50
|
+
#include "scanner.h"
|
51
|
+
|
52
|
+
#include "inherpsr.h"
|
53
|
+
|
54
|
+
/* =========================================
|
55
|
+
*****************************************
|
56
|
+
MACROS AND TYPES
|
57
|
+
=========================================
|
58
|
+
***************************************** */
|
59
|
+
typedef struct partialOrder PARTIAL_ORDER;
|
60
|
+
typedef struct successor SUCCESSOR;
|
61
|
+
|
62
|
+
struct partialOrder
|
63
|
+
{
|
64
|
+
Defclass *cls;
|
65
|
+
unsigned pre;
|
66
|
+
SUCCESSOR *suc;
|
67
|
+
struct partialOrder *nxt;
|
68
|
+
};
|
69
|
+
|
70
|
+
struct successor
|
71
|
+
{
|
72
|
+
PARTIAL_ORDER *po;
|
73
|
+
struct successor *nxt;
|
74
|
+
};
|
75
|
+
|
76
|
+
/***************************************/
|
77
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
78
|
+
/***************************************/
|
79
|
+
|
80
|
+
static PARTIAL_ORDER *InitializePartialOrderTable(Environment *,PARTIAL_ORDER *,PACKED_CLASS_LINKS *);
|
81
|
+
static void RecordPartialOrders(Environment *,PARTIAL_ORDER *,Defclass *,
|
82
|
+
PACKED_CLASS_LINKS *,unsigned long);
|
83
|
+
static PARTIAL_ORDER *FindPartialOrder(PARTIAL_ORDER *,Defclass *);
|
84
|
+
static void PrintPartialOrderLoop(Environment *,PARTIAL_ORDER *);
|
85
|
+
static void PrintClassLinks(Environment *,const char *,const char *,CLASS_LINK *);
|
86
|
+
|
87
|
+
/* =========================================
|
88
|
+
*****************************************
|
89
|
+
EXTERNALLY VISIBLE FUNCTIONS
|
90
|
+
=========================================
|
91
|
+
***************************************** */
|
92
|
+
|
93
|
+
/**************************************************************
|
94
|
+
NAME : ParseSuperclasses
|
95
|
+
DESCRIPTION : Parses the (is-a <superclass>+) portion of
|
96
|
+
the (defclass ...) construct and returns
|
97
|
+
a list of direct superclasses. The
|
98
|
+
class "standard-class" is the precedence list
|
99
|
+
for classes with no direct superclasses.
|
100
|
+
The final precedence list (not calculated here)
|
101
|
+
will have the class in question first followed
|
102
|
+
by the merged precedence lists of its direct
|
103
|
+
superclasses.
|
104
|
+
INPUTS : 1) The logical name of the input source
|
105
|
+
2) The symbolic name of the new class
|
106
|
+
RETURNS : The address of the superclass list
|
107
|
+
or NULL if there was an error
|
108
|
+
SIDE EFFECTS : None
|
109
|
+
NOTES : Assumes "(defclass <name> [<comment>] ("
|
110
|
+
has already been scanned.
|
111
|
+
|
112
|
+
All superclasses must be defined before
|
113
|
+
their subclasses. Duplicates in the (is-a
|
114
|
+
...) list are are not allowed (a class may only
|
115
|
+
inherits from a superclass once).
|
116
|
+
|
117
|
+
This routine also checks the class-precedence
|
118
|
+
lists of each of the direct superclasses for
|
119
|
+
an occurrence of the new class - i.e. cycles!
|
120
|
+
This can only happen when a class is redefined
|
121
|
+
(a new class cannot have an unspecified
|
122
|
+
superclass).
|
123
|
+
|
124
|
+
This routine allocates the space for the list
|
125
|
+
***************************************************************/
|
126
|
+
PACKED_CLASS_LINKS *ParseSuperclasses(
|
127
|
+
Environment *theEnv,
|
128
|
+
const char *readSource,
|
129
|
+
CLIPSLexeme *newClassName)
|
130
|
+
{
|
131
|
+
CLASS_LINK *clink = NULL,*cbot = NULL,*ctmp;
|
132
|
+
Defclass *sclass;
|
133
|
+
PACKED_CLASS_LINKS *plinks;
|
134
|
+
|
135
|
+
if (DefclassData(theEnv)->ObjectParseToken.tknType != LEFT_PARENTHESIS_TOKEN)
|
136
|
+
{
|
137
|
+
SyntaxErrorMessage(theEnv,"defclass inheritance");
|
138
|
+
return NULL;
|
139
|
+
}
|
140
|
+
GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
|
141
|
+
if ((DefclassData(theEnv)->ObjectParseToken.tknType != SYMBOL_TOKEN) ? true :
|
142
|
+
(DefclassData(theEnv)->ObjectParseToken.value != (void *) DefclassData(theEnv)->ISA_SYMBOL))
|
143
|
+
{
|
144
|
+
SyntaxErrorMessage(theEnv,"defclass inheritance");
|
145
|
+
return NULL;
|
146
|
+
}
|
147
|
+
SavePPBuffer(theEnv," ");
|
148
|
+
GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
|
149
|
+
while (DefclassData(theEnv)->ObjectParseToken.tknType != RIGHT_PARENTHESIS_TOKEN)
|
150
|
+
{
|
151
|
+
if (DefclassData(theEnv)->ObjectParseToken.tknType != SYMBOL_TOKEN)
|
152
|
+
{
|
153
|
+
SyntaxErrorMessage(theEnv,"defclass");
|
154
|
+
goto SuperclassParseError;
|
155
|
+
}
|
156
|
+
if (FindModuleSeparator(newClassName->contents))
|
157
|
+
{
|
158
|
+
IllegalModuleSpecifierMessage(theEnv);
|
159
|
+
goto SuperclassParseError;
|
160
|
+
}
|
161
|
+
if (DefclassData(theEnv)->ObjectParseToken.value == (void *) newClassName)
|
162
|
+
{
|
163
|
+
PrintErrorID(theEnv,"INHERPSR",1,false);
|
164
|
+
WriteString(theEnv,STDERR,"A class may not have itself as a superclass.\n");
|
165
|
+
goto SuperclassParseError;
|
166
|
+
}
|
167
|
+
for (ctmp = clink ; ctmp != NULL ; ctmp = ctmp->nxt)
|
168
|
+
{
|
169
|
+
if (DefclassData(theEnv)->ObjectParseToken.value == (void *) ctmp->cls->header.name)
|
170
|
+
{
|
171
|
+
PrintErrorID(theEnv,"INHERPSR",2,false);
|
172
|
+
WriteString(theEnv,STDERR,"A class may inherit from a superclass only once.\n");
|
173
|
+
goto SuperclassParseError;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
sclass = LookupDefclassInScope(theEnv,DefclassData(theEnv)->ObjectParseToken.lexemeValue->contents);
|
177
|
+
if (sclass == NULL)
|
178
|
+
{
|
179
|
+
PrintErrorID(theEnv,"INHERPSR",3,false);
|
180
|
+
WriteString(theEnv,STDERR,"A class must be defined after all its superclasses.\n");
|
181
|
+
goto SuperclassParseError;
|
182
|
+
}
|
183
|
+
if ((sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_NAME_TYPE]) ||
|
184
|
+
(sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_ADDRESS_TYPE]) ||
|
185
|
+
(sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_NAME_TYPE]->directSuperclasses.classArray[0]))
|
186
|
+
{
|
187
|
+
PrintErrorID(theEnv,"INHERPSR",6,false);
|
188
|
+
WriteString(theEnv,STDERR,"A user-defined class cannot be a subclass of '");
|
189
|
+
WriteString(theEnv,STDERR,DefclassName(sclass));
|
190
|
+
WriteString(theEnv,STDERR,"'.\n");
|
191
|
+
goto SuperclassParseError;
|
192
|
+
}
|
193
|
+
ctmp = get_struct(theEnv,classLink);
|
194
|
+
ctmp->cls = sclass;
|
195
|
+
if (clink == NULL)
|
196
|
+
clink = ctmp;
|
197
|
+
else
|
198
|
+
cbot->nxt = ctmp;
|
199
|
+
ctmp->nxt = NULL;
|
200
|
+
cbot = ctmp;
|
201
|
+
|
202
|
+
SavePPBuffer(theEnv," ");
|
203
|
+
GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
|
204
|
+
}
|
205
|
+
if (clink == NULL)
|
206
|
+
{
|
207
|
+
PrintErrorID(theEnv,"INHERPSR",4,false);
|
208
|
+
WriteString(theEnv,STDERR,"A class must have at least one superclass.\n");
|
209
|
+
return NULL;
|
210
|
+
}
|
211
|
+
PPBackup(theEnv);
|
212
|
+
PPBackup(theEnv);
|
213
|
+
SavePPBuffer(theEnv,")");
|
214
|
+
plinks = get_struct(theEnv,packedClassLinks);
|
215
|
+
PackClassLinks(theEnv,plinks,clink);
|
216
|
+
return(plinks);
|
217
|
+
|
218
|
+
SuperclassParseError:
|
219
|
+
DeleteClassLinks(theEnv,clink);
|
220
|
+
return NULL;
|
221
|
+
}
|
222
|
+
|
223
|
+
/***************************************************************************
|
224
|
+
NAME : FindPrecedenceList
|
225
|
+
DESCRIPTION : A complete class precedence list is obtained from the
|
226
|
+
list of direct superclasses as follows :
|
227
|
+
|
228
|
+
Each class and its direct superclasses are recursively
|
229
|
+
entered in order to a list called the partial order table.
|
230
|
+
A class is only entered once. The order reflects a pre-order
|
231
|
+
depth-first traversal of the classes, and this order will be
|
232
|
+
followed as closely as possible to preserve the "family"
|
233
|
+
heuristic when constructing the class precedence list.
|
234
|
+
|
235
|
+
Attached to each node is a count indicating the number of
|
236
|
+
classes which must precede this class and a list of classes
|
237
|
+
which must succeed this class (attached via the suc field and
|
238
|
+
linked via nxt fields). These predecessor counts
|
239
|
+
and successor lists indicate the partial orderings given
|
240
|
+
by the rules of multiple inheritance for the classes:
|
241
|
+
1) a class must precede all its superclasses, and 2) a
|
242
|
+
class determines the precedence of its immediate superclasses.
|
243
|
+
|
244
|
+
For example, the following class definitions
|
245
|
+
|
246
|
+
(defclass A (is-a USER))
|
247
|
+
(defclass B (is-a USER))
|
248
|
+
(defclass C (is-a A B))
|
249
|
+
|
250
|
+
would give the following partial orders:
|
251
|
+
|
252
|
+
C < A by Rule 1
|
253
|
+
C < B by Rule 1
|
254
|
+
A < B by Rule 2
|
255
|
+
B < USER by Rule 1
|
256
|
+
A < USER by Rule 1
|
257
|
+
USER < OBJECT by Rule 1
|
258
|
+
|
259
|
+
In turn, these partial orders would be recorded in a
|
260
|
+
sequence table:
|
261
|
+
|
262
|
+
C A USER OBJECT B
|
263
|
+
Predecessor Count 0 1 2 1 2
|
264
|
+
Successor List A,B B,USER OBJECT <NIL> USER
|
265
|
+
|
266
|
+
To generate a precedence list for C, we pick the first
|
267
|
+
class with a predecessor count of 0, append it to the
|
268
|
+
precedence list, and decrement the counts of all its
|
269
|
+
successors. We continue scanning for a 0 from where
|
270
|
+
we left off. If we ever scan completely through the
|
271
|
+
table without finding a 0, then we know there is an
|
272
|
+
error.
|
273
|
+
|
274
|
+
Shown below is the table above after each class is
|
275
|
+
entered onto the precedence list:
|
276
|
+
|
277
|
+
Precedence list: C
|
278
|
+
A USER OBJECT B
|
279
|
+
Predecessor Count 0 2 1 1
|
280
|
+
Successor List B,USER OBJECT <NIL> USER
|
281
|
+
|
282
|
+
Precedence list: C A
|
283
|
+
USER OBJECT B
|
284
|
+
Predecessor Count 1 1 0
|
285
|
+
Successor List OBJECT <NIL> USER
|
286
|
+
|
287
|
+
Precedence list: C A B
|
288
|
+
USER OBJECT
|
289
|
+
Predecessor Count 0 1
|
290
|
+
Successor List OBJECT <NIL>
|
291
|
+
|
292
|
+
Precedence list: C A B USER
|
293
|
+
OBJECT
|
294
|
+
Predecessor Count 0
|
295
|
+
Successor List <NIL>
|
296
|
+
|
297
|
+
Precedence List: C A B USER OBJECT
|
298
|
+
|
299
|
+
And since the table is now empty we are done!
|
300
|
+
INPUTS : 1) The old class definition (NULL if it is new)
|
301
|
+
2) The list of direct superclasses
|
302
|
+
RETURNS : The address of the precedence list if successful,
|
303
|
+
NULL otherwise
|
304
|
+
SIDE EFFECTS : Precedence list allocated
|
305
|
+
NOTES : WARNING!! - This routine assumes that there are no
|
306
|
+
cyclic dependencies in the given superclass list, i.e.
|
307
|
+
none of the superclasses inherit from the class for
|
308
|
+
which the precedence list is being defined. (This
|
309
|
+
is verified in ParseDefclasses() in CLASSCOM.C)
|
310
|
+
|
311
|
+
Every class-precedence list has the class itself on it
|
312
|
+
(implicitly) and a built-in system class on it explicitly
|
313
|
+
(except for the built-in classes).
|
314
|
+
|
315
|
+
The precedence determination algorithm is a variation on
|
316
|
+
the topological sorting algorithm given in The Art of
|
317
|
+
Computer Programming - Vol. I (Fundamental Algorithms) by
|
318
|
+
Donald Knuth.
|
319
|
+
***************************************************************************/
|
320
|
+
PACKED_CLASS_LINKS *FindPrecedenceList(
|
321
|
+
Environment *theEnv,
|
322
|
+
Defclass *cls,
|
323
|
+
PACKED_CLASS_LINKS *supers)
|
324
|
+
{
|
325
|
+
PARTIAL_ORDER *po_table = NULL,*start,*pop,*poprv,*potmp;
|
326
|
+
SUCCESSOR *stmp;
|
327
|
+
CLASS_LINK *ptop,*pbot,*ptmp;
|
328
|
+
PACKED_CLASS_LINKS *plinks;
|
329
|
+
unsigned long i;
|
330
|
+
|
331
|
+
/* =====================================================================
|
332
|
+
Recursively add all superclasses in a pre-order depth-first traversal
|
333
|
+
to the partial order table. There should be only one node per class.
|
334
|
+
===================================================================== */
|
335
|
+
po_table = InitializePartialOrderTable(theEnv,po_table,supers);
|
336
|
+
|
337
|
+
/* =============================================================
|
338
|
+
If the class already exists, record the rule 1 partial orders
|
339
|
+
with the new superclass lists. This is so that cyclic
|
340
|
+
dependencies can be detected.
|
341
|
+
============================================================= */
|
342
|
+
if (cls != NULL)
|
343
|
+
{
|
344
|
+
pop = get_struct(theEnv,partialOrder);
|
345
|
+
pop->cls = cls;
|
346
|
+
pop->pre = 0;
|
347
|
+
pop->suc = NULL;
|
348
|
+
pop->nxt = po_table;
|
349
|
+
po_table = pop;
|
350
|
+
pop = po_table->nxt;
|
351
|
+
RecordPartialOrders(theEnv,po_table,cls,supers,0);
|
352
|
+
}
|
353
|
+
else
|
354
|
+
pop = po_table;
|
355
|
+
|
356
|
+
/* ==================================================================
|
357
|
+
Record the rule 1 and rule 2 partial orders given by the direct
|
358
|
+
superclass lists of the classes in the table. There is no need to
|
359
|
+
recurse since all possible classes have been entered already.
|
360
|
+
|
361
|
+
Be sure to skip the class itself if it was added to the front of
|
362
|
+
the table.
|
363
|
+
================================================================== */
|
364
|
+
for ( ; pop != NULL ; pop = pop->nxt)
|
365
|
+
{
|
366
|
+
RecordPartialOrders(theEnv,po_table,pop->cls,&pop->cls->directSuperclasses,0);
|
367
|
+
for (i = 0 ; i < pop->cls->directSuperclasses.classCount ; i++)
|
368
|
+
RecordPartialOrders(theEnv,po_table,pop->cls->directSuperclasses.classArray[i],
|
369
|
+
&pop->cls->directSuperclasses,i+1);
|
370
|
+
}
|
371
|
+
|
372
|
+
/* =============================================================
|
373
|
+
Record the rule 2 partial orders given by the superclass list
|
374
|
+
============================================================= */
|
375
|
+
for (i = 0 ; i < supers->classCount ; i++)
|
376
|
+
RecordPartialOrders(theEnv,po_table,supers->classArray[i],supers,i+1);
|
377
|
+
|
378
|
+
start = NULL;
|
379
|
+
poprv = NULL;
|
380
|
+
pop = po_table;
|
381
|
+
ptop = pbot = NULL;
|
382
|
+
while (pop != start)
|
383
|
+
{
|
384
|
+
/* ==============================================================
|
385
|
+
Allow wraparound - happens when the search for a 0 node begins
|
386
|
+
somewhere in the middle of the sequence table
|
387
|
+
============================================================== */
|
388
|
+
if (pop == NULL)
|
389
|
+
{
|
390
|
+
poprv = NULL;
|
391
|
+
pop = po_table;
|
392
|
+
start = start->nxt;
|
393
|
+
}
|
394
|
+
|
395
|
+
/* =========================================================
|
396
|
+
Search for the first class with no remaining predecessors
|
397
|
+
========================================================= */
|
398
|
+
if (pop->pre == 0)
|
399
|
+
{
|
400
|
+
/* =================================================
|
401
|
+
Decrement the predecessor count for all the
|
402
|
+
successors of this class and delete the list.
|
403
|
+
|
404
|
+
This is the variation on Knuth's algorithm which
|
405
|
+
allows us to preserve the "family" heuristic.
|
406
|
+
Since we will pick up scanning for 0's from
|
407
|
+
this point, we will be able to keep "family"
|
408
|
+
trees together, if possible. BuildPartialOrders()
|
409
|
+
entered the classes into the sequence table
|
410
|
+
in a pre-order depth traversal order.
|
411
|
+
================================================= */
|
412
|
+
while (pop->suc != NULL)
|
413
|
+
{
|
414
|
+
stmp = pop->suc;
|
415
|
+
pop->suc = stmp->nxt;
|
416
|
+
stmp->po->pre--;
|
417
|
+
rtn_struct(theEnv,successor,stmp);
|
418
|
+
}
|
419
|
+
|
420
|
+
/* =============================================
|
421
|
+
Append the class to the precedence list and
|
422
|
+
remove its entry from the partial order table
|
423
|
+
============================================= */
|
424
|
+
potmp = pop;
|
425
|
+
if (poprv == NULL)
|
426
|
+
po_table = pop->nxt;
|
427
|
+
else
|
428
|
+
poprv->nxt = pop->nxt;
|
429
|
+
pop = pop->nxt;
|
430
|
+
start = poprv;
|
431
|
+
ptmp = get_struct(theEnv,classLink);
|
432
|
+
ptmp->cls = potmp->cls;
|
433
|
+
ptmp->nxt = NULL;
|
434
|
+
rtn_struct(theEnv,partialOrder,potmp);
|
435
|
+
if (ptop == NULL)
|
436
|
+
ptop = ptmp;
|
437
|
+
else
|
438
|
+
pbot->nxt = ptmp;
|
439
|
+
pbot = ptmp;
|
440
|
+
}
|
441
|
+
else
|
442
|
+
{
|
443
|
+
poprv = pop;
|
444
|
+
pop = pop->nxt;
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
/* ======================================================================
|
449
|
+
If the table of partial orders is not empty and we were unable to find
|
450
|
+
a class with no predecessors, then there is no solution! Print out the
|
451
|
+
precedence loop in the partial orders. Delete the remaining partial
|
452
|
+
order table and the partial precedence list.
|
453
|
+
====================================================================== */
|
454
|
+
if (po_table != NULL)
|
455
|
+
{
|
456
|
+
PrintErrorID(theEnv,"INHERPSR",5,false);
|
457
|
+
PrintClassLinks(theEnv,STDERR,"Partial precedence list formed:",ptop);
|
458
|
+
PrintPartialOrderLoop(theEnv,po_table);
|
459
|
+
while (po_table != NULL)
|
460
|
+
{
|
461
|
+
while (po_table->suc != NULL)
|
462
|
+
{
|
463
|
+
stmp = po_table->suc;
|
464
|
+
po_table->suc = stmp->nxt;
|
465
|
+
rtn_struct(theEnv,successor,stmp);
|
466
|
+
}
|
467
|
+
potmp = po_table;
|
468
|
+
po_table = po_table->nxt;
|
469
|
+
rtn_struct(theEnv,partialOrder,potmp);
|
470
|
+
}
|
471
|
+
DeleteClassLinks(theEnv,ptop);
|
472
|
+
return NULL;
|
473
|
+
}
|
474
|
+
|
475
|
+
/* =============================================================================
|
476
|
+
If the class already existed, be sure and remove it from its own precedence
|
477
|
+
list. Remember that we stuck it on the table artificially to catch cycles.
|
478
|
+
It was first in the table, and, since it started with a predecessor count
|
479
|
+
of zero (given that there were no loops), it is first in the precedence list.
|
480
|
+
|
481
|
+
We will leave the dummy node there so that functions which wish to iterate
|
482
|
+
over a class and its superclasses may easily do so.
|
483
|
+
============================================================================= */
|
484
|
+
if (cls == NULL)
|
485
|
+
{
|
486
|
+
ptmp = get_struct(theEnv,classLink);
|
487
|
+
ptmp->nxt = ptop;
|
488
|
+
ptop = ptmp;
|
489
|
+
}
|
490
|
+
|
491
|
+
/* ============================================================
|
492
|
+
The class pointer will be filled in later by ParseDefclass()
|
493
|
+
============================================================ */
|
494
|
+
ptop->cls = NULL;
|
495
|
+
|
496
|
+
plinks = get_struct(theEnv,packedClassLinks);
|
497
|
+
PackClassLinks(theEnv,plinks,ptop);
|
498
|
+
return(plinks);
|
499
|
+
}
|
500
|
+
|
501
|
+
/***************************************************
|
502
|
+
NAME : PackClassLinks
|
503
|
+
DESCRIPTION : Writes a list of class links into
|
504
|
+
a contiguous section of memory to
|
505
|
+
reduce overhead (the original list
|
506
|
+
is deleted)
|
507
|
+
INPUTS : 1) The packed list structure to use
|
508
|
+
2) The top of the original list
|
509
|
+
RETURNS : Nothing useful
|
510
|
+
SIDE EFFECTS : Packed list allocated and old list
|
511
|
+
deleted
|
512
|
+
NOTES : None
|
513
|
+
***************************************************/
|
514
|
+
void PackClassLinks(
|
515
|
+
Environment *theEnv,
|
516
|
+
PACKED_CLASS_LINKS *plinks,
|
517
|
+
CLASS_LINK *lptop)
|
518
|
+
{
|
519
|
+
unsigned count;
|
520
|
+
CLASS_LINK *lp;
|
521
|
+
|
522
|
+
for (count = 0 , lp = lptop ; lp != NULL ; lp = lp->nxt)
|
523
|
+
count++;
|
524
|
+
if (count > 0)
|
525
|
+
plinks->classArray = (Defclass **) gm2(theEnv,(sizeof(Defclass *) * count));
|
526
|
+
else
|
527
|
+
plinks->classArray = NULL;
|
528
|
+
for (count = 0 , lp = lptop ; lp != NULL ; lp = lp->nxt , count++)
|
529
|
+
plinks->classArray[count] = lp->cls;
|
530
|
+
DeleteClassLinks(theEnv,lptop);
|
531
|
+
plinks->classCount = count;
|
532
|
+
}
|
533
|
+
|
534
|
+
/* =========================================
|
535
|
+
*****************************************
|
536
|
+
INTERNALLY VISIBLE FUNCTIONS
|
537
|
+
=========================================
|
538
|
+
***************************************** */
|
539
|
+
|
540
|
+
/**************************************************************************
|
541
|
+
NAME : InitializePartialOrderTable
|
542
|
+
DESCRIPTION : This function recursively enters the classes
|
543
|
+
that will be used in a precedence list
|
544
|
+
determination in depth-first pre-order traversal.
|
545
|
+
The predecessor counts and successor list are initialized.
|
546
|
+
|
547
|
+
INPUTS : 1) The partial order table
|
548
|
+
2) A list of direct superclasses
|
549
|
+
3) The class for which a precedence class is being
|
550
|
+
determined (NULL for new class)
|
551
|
+
4) The class which superclass list is being processed
|
552
|
+
RETURNS : The top of partial order table
|
553
|
+
SIDE EFFECTS : The partial order table is initialized.
|
554
|
+
NOTES : None
|
555
|
+
**************************************************************************/
|
556
|
+
static PARTIAL_ORDER *InitializePartialOrderTable(
|
557
|
+
Environment *theEnv,
|
558
|
+
PARTIAL_ORDER *po_table,
|
559
|
+
PACKED_CLASS_LINKS *supers)
|
560
|
+
{
|
561
|
+
PARTIAL_ORDER *pop,*poprv;
|
562
|
+
unsigned long i;
|
563
|
+
|
564
|
+
for (i = 0 ; i < supers->classCount ; i++)
|
565
|
+
{
|
566
|
+
/* =================================================
|
567
|
+
Append this class at the end of the partial order
|
568
|
+
table only if it is not already present
|
569
|
+
================================================= */
|
570
|
+
poprv = NULL;
|
571
|
+
for (pop = po_table ; pop != NULL ; pop = pop->nxt)
|
572
|
+
{
|
573
|
+
if (pop->cls == supers->classArray[i])
|
574
|
+
break;
|
575
|
+
poprv = pop;
|
576
|
+
}
|
577
|
+
if (pop == NULL)
|
578
|
+
{
|
579
|
+
pop = get_struct(theEnv,partialOrder);
|
580
|
+
pop->cls = supers->classArray[i];
|
581
|
+
pop->nxt = NULL;
|
582
|
+
pop->suc = NULL;
|
583
|
+
pop->pre = 0;
|
584
|
+
if (poprv == NULL)
|
585
|
+
po_table = pop;
|
586
|
+
else
|
587
|
+
poprv->nxt = pop;
|
588
|
+
|
589
|
+
/* =============================================================
|
590
|
+
Recursively append all its superclasses immediately after it.
|
591
|
+
This order will allow us to preserve the "family" heuristic
|
592
|
+
in the precedence list.
|
593
|
+
============================================================= */
|
594
|
+
po_table = InitializePartialOrderTable(theEnv,po_table,
|
595
|
+
&supers->classArray[i]->directSuperclasses);
|
596
|
+
}
|
597
|
+
}
|
598
|
+
return(po_table);
|
599
|
+
}
|
600
|
+
|
601
|
+
/***********************************************************************************
|
602
|
+
NAME : RecordPartialOrders
|
603
|
+
DESCRIPTION : Given a predecessor class and a list of successor classes, this
|
604
|
+
function enters a number of partial orders into the table equaling
|
605
|
+
the number of successor classes.
|
606
|
+
INPUTS : 1) The partial order table
|
607
|
+
2) The predecessor class
|
608
|
+
3) An array of successor classes
|
609
|
+
4) A starting index for the successor classes
|
610
|
+
RETURNS : The top of sequence table
|
611
|
+
SIDE EFFECTS : The sequence table is built, e.g.:
|
612
|
+
|
613
|
+
CLASS1 < CLASS2 , CLASS3
|
614
|
+
|
615
|
+
would be recorded as:
|
616
|
+
|
617
|
+
PO_TABLE -> NXT -> NXT -> NXT -> <NIL>
|
618
|
+
<CLASS1> <CLASS2> <CLASS3>
|
619
|
+
SUC SUC SUC
|
620
|
+
| | |
|
621
|
+
V V V
|
622
|
+
<CLASS2> <NIL> <NIL>
|
623
|
+
NXT
|
624
|
+
|
|
625
|
+
V
|
626
|
+
<CLASS3>
|
627
|
+
NXT
|
628
|
+
|
|
629
|
+
V
|
630
|
+
<NIL>
|
631
|
+
|
632
|
+
The predecessor counts would be 0, 1 and 1 for CLASS1, CLASS2
|
633
|
+
and CLASS3 respectively.
|
634
|
+
NOTES : None
|
635
|
+
***********************************************************************************/
|
636
|
+
static void RecordPartialOrders(
|
637
|
+
Environment *theEnv,
|
638
|
+
PARTIAL_ORDER *po_table,
|
639
|
+
Defclass *cls,
|
640
|
+
PACKED_CLASS_LINKS *successors,
|
641
|
+
unsigned long starti)
|
642
|
+
{
|
643
|
+
PARTIAL_ORDER *clspo;
|
644
|
+
SUCCESSOR *stmp;
|
645
|
+
|
646
|
+
clspo = FindPartialOrder(po_table,cls);
|
647
|
+
while (starti < successors->classCount)
|
648
|
+
{
|
649
|
+
stmp = get_struct(theEnv,successor);
|
650
|
+
stmp->po = FindPartialOrder(po_table,successors->classArray[starti]);
|
651
|
+
stmp->nxt = clspo->suc;
|
652
|
+
clspo->suc = stmp;
|
653
|
+
stmp->po->pre++;
|
654
|
+
starti++;
|
655
|
+
}
|
656
|
+
}
|
657
|
+
|
658
|
+
/***************************************************
|
659
|
+
NAME : FindPartialOrder
|
660
|
+
DESCRIPTION : Finds a partial order node
|
661
|
+
INPUTS : 1) The partial order table
|
662
|
+
2) The class to look up
|
663
|
+
RETURNS : The partial order node address
|
664
|
+
SIDE EFFECTS : None
|
665
|
+
NOTES : None
|
666
|
+
***************************************************/
|
667
|
+
static PARTIAL_ORDER *FindPartialOrder(
|
668
|
+
PARTIAL_ORDER *po_table,
|
669
|
+
Defclass *cls)
|
670
|
+
{
|
671
|
+
while (po_table != NULL)
|
672
|
+
{
|
673
|
+
if (po_table->cls == cls)
|
674
|
+
break;
|
675
|
+
po_table = po_table->nxt;
|
676
|
+
}
|
677
|
+
return(po_table);
|
678
|
+
}
|
679
|
+
|
680
|
+
/**************************************************************************
|
681
|
+
NAME : PrintPartialOrderLoop
|
682
|
+
DESCRIPTION : This routine prints a conflicting loop (there may be more
|
683
|
+
than one) in the given sequence table of partial orders.
|
684
|
+
|
685
|
+
The algorithm works as follows:
|
686
|
+
|
687
|
+
Given the following class definitions,
|
688
|
+
|
689
|
+
(defclass A (is-a USER))
|
690
|
+
(defclass B (is-a USER))
|
691
|
+
(defclass C (is-a A B))
|
692
|
+
(defclass D (is-a B A))
|
693
|
+
(defclass E (is-a C D))
|
694
|
+
|
695
|
+
the partial order table will look as follows after as many
|
696
|
+
classes as possible have been entered onto the precedence
|
697
|
+
list:
|
698
|
+
|
699
|
+
A USER OBJECT B
|
700
|
+
Predecessor Count 1 2 1 1
|
701
|
+
Successor List B,USER OBJECT <NIL> A,USER
|
702
|
+
|
703
|
+
Construct a new table where each class is linked to one
|
704
|
+
of its predecessors. For the example above one would be:
|
705
|
+
|
706
|
+
Class: A USER OBJECT B
|
707
|
+
Predecessor: B A USER A
|
708
|
+
|
709
|
+
This table is actually implemnted using the original
|
710
|
+
partial order table (see the code below for specifics).
|
711
|
+
Now using this table, start with the first node, and visit
|
712
|
+
successive nodes by following the predecessor links. Mark
|
713
|
+
each node as "visited". When a previously visited node is
|
714
|
+
encountered, the loop has been found.
|
715
|
+
|
716
|
+
In the case above, we start with A, goto B and then goto A
|
717
|
+
again which we have already seen. So starting from where
|
718
|
+
we found the loop (A) we follow the links again, printing
|
719
|
+
the nodes as we go, until we're back where we started:
|
720
|
+
A B A. Notice that this loop reflects the Rule 2 conflicts
|
721
|
+
between Class C and Class D in Class E's precedence list.
|
722
|
+
|
723
|
+
INPUTS : The remaining partial order table of conflicting partial
|
724
|
+
orders
|
725
|
+
RETURNS : Nothing useful
|
726
|
+
SIDE EFFECTS : The predecessor counts and successor lists are modified to
|
727
|
+
implement the loop detection.
|
728
|
+
NOTES : This algorithm is adopted from one given in Donald
|
729
|
+
Knuth's The Art of Computer Programming - Vol. I
|
730
|
+
(Fundamental Algorithms).
|
731
|
+
**************************************************************************/
|
732
|
+
static void PrintPartialOrderLoop(
|
733
|
+
Environment *theEnv,
|
734
|
+
PARTIAL_ORDER *po_table)
|
735
|
+
{
|
736
|
+
PARTIAL_ORDER *pop1,*pop2;
|
737
|
+
SUCCESSOR *prc,*stmp;
|
738
|
+
|
739
|
+
/* ====================================================
|
740
|
+
Set the predecessor count of every node to 0 so that
|
741
|
+
this field can be used as a marker
|
742
|
+
==================================================== */
|
743
|
+
for (pop1 = po_table ; pop1 != NULL ; pop1 = pop1->nxt)
|
744
|
+
pop1->pre = 0;
|
745
|
+
|
746
|
+
/* =======================================================
|
747
|
+
Mark each node in the partial order table with one of
|
748
|
+
its predecessors. If the class has already been marked
|
749
|
+
(predecessor count > 0), don't bother. This is
|
750
|
+
accomplished by adding a node to the front of its
|
751
|
+
successors' successor lists.
|
752
|
+
|
753
|
+
When the process is finished, all nodes will have one
|
754
|
+
predecessor chained to them by their 'suc' field.
|
755
|
+
(If any nodes had had no predecessors, they would not
|
756
|
+
still be in the table.)
|
757
|
+
======================================================= */
|
758
|
+
for (pop1 = po_table ; pop1 != NULL ; pop1 = pop1->nxt)
|
759
|
+
{
|
760
|
+
if (pop1->pre == 0)
|
761
|
+
{
|
762
|
+
prc = pop1->suc;
|
763
|
+
pop1->suc = NULL;
|
764
|
+
}
|
765
|
+
else
|
766
|
+
{
|
767
|
+
prc = pop1->suc->nxt;
|
768
|
+
pop1->suc->nxt = NULL;
|
769
|
+
}
|
770
|
+
while (prc != NULL)
|
771
|
+
{
|
772
|
+
pop2 = FindPartialOrder(po_table,prc->po->cls);
|
773
|
+
if (pop2->pre == 0)
|
774
|
+
{
|
775
|
+
stmp = get_struct(theEnv,successor);
|
776
|
+
stmp->po = pop1;
|
777
|
+
stmp->nxt = pop2->suc;
|
778
|
+
pop2->suc = stmp;
|
779
|
+
pop2->pre = 1;
|
780
|
+
}
|
781
|
+
stmp = prc;
|
782
|
+
prc = prc->nxt;
|
783
|
+
rtn_struct(theEnv,successor,stmp);
|
784
|
+
}
|
785
|
+
}
|
786
|
+
|
787
|
+
/* =================================================
|
788
|
+
Set the predecessor count of every node back to 0
|
789
|
+
so that this field can be used as a marker again
|
790
|
+
================================================= */
|
791
|
+
for (pop1 = po_table ; pop1 != NULL ; pop1 = pop1->nxt)
|
792
|
+
pop1->pre = 0;
|
793
|
+
|
794
|
+
/* =========================================================
|
795
|
+
Now start with the first node in the partial order table,
|
796
|
+
and follow the predecessor links, marking the
|
797
|
+
nodes as they are visited. When we reach a node
|
798
|
+
we have been before, we have found a loop!
|
799
|
+
Follow all the marked nodes again starting from the
|
800
|
+
CURRENT position to print the loop.
|
801
|
+
========================================================= */
|
802
|
+
pop1 = po_table;
|
803
|
+
while (pop1->pre == 0)
|
804
|
+
{
|
805
|
+
pop1->pre = 1;
|
806
|
+
pop1 = pop1->suc->po;
|
807
|
+
}
|
808
|
+
|
809
|
+
WriteString(theEnv,STDERR,"Precedence loop in superclasses:");
|
810
|
+
while (pop1->pre == 1)
|
811
|
+
{
|
812
|
+
WriteString(theEnv,STDERR," ");
|
813
|
+
PrintClassName(theEnv,STDERR,pop1->cls,false,false);
|
814
|
+
pop1->pre = 0;
|
815
|
+
pop1 = pop1->suc->po;
|
816
|
+
}
|
817
|
+
WriteString(theEnv,STDERR," ");
|
818
|
+
PrintClassName(theEnv,STDERR,pop1->cls,false,true);
|
819
|
+
}
|
820
|
+
|
821
|
+
/***************************************************
|
822
|
+
NAME : PrintClassLinks
|
823
|
+
DESCRIPTION : Displays the names of classes in
|
824
|
+
a list with a title
|
825
|
+
INPUTS : 1) The logical name of the output
|
826
|
+
2) Title string
|
827
|
+
3) List of class links
|
828
|
+
RETURNS : Nothing useful
|
829
|
+
SIDE EFFECTS : None
|
830
|
+
NOTES : None
|
831
|
+
***************************************************/
|
832
|
+
static void PrintClassLinks(
|
833
|
+
Environment *theEnv,
|
834
|
+
const char *logicalName,
|
835
|
+
const char *title,
|
836
|
+
CLASS_LINK *clink)
|
837
|
+
{
|
838
|
+
if (title != NULL)
|
839
|
+
WriteString(theEnv,logicalName,title);
|
840
|
+
while (clink != NULL)
|
841
|
+
{
|
842
|
+
WriteString(theEnv,logicalName," ");
|
843
|
+
PrintClassName(theEnv,logicalName,clink->cls,false,false);
|
844
|
+
clink = clink->nxt;
|
845
|
+
}
|
846
|
+
WriteString(theEnv,logicalName,"\n");
|
847
|
+
}
|
848
|
+
|
849
|
+
#endif
|
850
|
+
|