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.
Files changed (346) hide show
  1. checksums.yaml +7 -0
  2. data/ext/clipsruby/agenda.c +1373 -0
  3. data/ext/clipsruby/agenda.h +169 -0
  4. data/ext/clipsruby/analysis.c +1142 -0
  5. data/ext/clipsruby/analysis.h +61 -0
  6. data/ext/clipsruby/argacces.c +526 -0
  7. data/ext/clipsruby/argacces.h +77 -0
  8. data/ext/clipsruby/bload.c +884 -0
  9. data/ext/clipsruby/bload.h +94 -0
  10. data/ext/clipsruby/bmathfun.c +557 -0
  11. data/ext/clipsruby/bmathfun.h +66 -0
  12. data/ext/clipsruby/bsave.c +634 -0
  13. data/ext/clipsruby/bsave.h +130 -0
  14. data/ext/clipsruby/classcom.c +976 -0
  15. data/ext/clipsruby/classcom.h +115 -0
  16. data/ext/clipsruby/classexm.c +1376 -0
  17. data/ext/clipsruby/classexm.h +97 -0
  18. data/ext/clipsruby/classfun.c +1392 -0
  19. data/ext/clipsruby/classfun.h +164 -0
  20. data/ext/clipsruby/classinf.c +1245 -0
  21. data/ext/clipsruby/classinf.h +94 -0
  22. data/ext/clipsruby/classini.c +843 -0
  23. data/ext/clipsruby/classini.h +75 -0
  24. data/ext/clipsruby/classpsr.c +957 -0
  25. data/ext/clipsruby/classpsr.h +73 -0
  26. data/ext/clipsruby/clips.h +133 -0
  27. data/ext/clipsruby/clipsruby.c +619 -0
  28. data/ext/clipsruby/clsltpsr.c +931 -0
  29. data/ext/clipsruby/clsltpsr.h +72 -0
  30. data/ext/clipsruby/commline.c +1217 -0
  31. data/ext/clipsruby/commline.h +131 -0
  32. data/ext/clipsruby/conscomp.c +1593 -0
  33. data/ext/clipsruby/conscomp.h +150 -0
  34. data/ext/clipsruby/constant.h +264 -0
  35. data/ext/clipsruby/constrct.c +1090 -0
  36. data/ext/clipsruby/constrct.h +216 -0
  37. data/ext/clipsruby/constrnt.c +554 -0
  38. data/ext/clipsruby/constrnt.h +132 -0
  39. data/ext/clipsruby/crstrtgy.c +1088 -0
  40. data/ext/clipsruby/crstrtgy.h +85 -0
  41. data/ext/clipsruby/cstrcbin.c +185 -0
  42. data/ext/clipsruby/cstrcbin.h +61 -0
  43. data/ext/clipsruby/cstrccmp.h +43 -0
  44. data/ext/clipsruby/cstrccom.c +1791 -0
  45. data/ext/clipsruby/cstrccom.h +115 -0
  46. data/ext/clipsruby/cstrcpsr.c +835 -0
  47. data/ext/clipsruby/cstrcpsr.h +97 -0
  48. data/ext/clipsruby/cstrnbin.c +282 -0
  49. data/ext/clipsruby/cstrnbin.h +55 -0
  50. data/ext/clipsruby/cstrnchk.c +826 -0
  51. data/ext/clipsruby/cstrnchk.h +91 -0
  52. data/ext/clipsruby/cstrncmp.c +238 -0
  53. data/ext/clipsruby/cstrncmp.h +57 -0
  54. data/ext/clipsruby/cstrnops.c +1176 -0
  55. data/ext/clipsruby/cstrnops.h +47 -0
  56. data/ext/clipsruby/cstrnpsr.c +1394 -0
  57. data/ext/clipsruby/cstrnpsr.h +88 -0
  58. data/ext/clipsruby/cstrnutl.c +564 -0
  59. data/ext/clipsruby/cstrnutl.h +54 -0
  60. data/ext/clipsruby/default.c +454 -0
  61. data/ext/clipsruby/default.h +57 -0
  62. data/ext/clipsruby/defins.c +971 -0
  63. data/ext/clipsruby/defins.h +127 -0
  64. data/ext/clipsruby/developr.c +677 -0
  65. data/ext/clipsruby/developr.h +69 -0
  66. data/ext/clipsruby/dffctbin.c +477 -0
  67. data/ext/clipsruby/dffctbin.h +76 -0
  68. data/ext/clipsruby/dffctbsc.c +308 -0
  69. data/ext/clipsruby/dffctbsc.h +72 -0
  70. data/ext/clipsruby/dffctcmp.c +297 -0
  71. data/ext/clipsruby/dffctcmp.h +44 -0
  72. data/ext/clipsruby/dffctdef.c +364 -0
  73. data/ext/clipsruby/dffctdef.h +104 -0
  74. data/ext/clipsruby/dffctpsr.c +179 -0
  75. data/ext/clipsruby/dffctpsr.h +49 -0
  76. data/ext/clipsruby/dffnxbin.c +520 -0
  77. data/ext/clipsruby/dffnxbin.h +67 -0
  78. data/ext/clipsruby/dffnxcmp.c +378 -0
  79. data/ext/clipsruby/dffnxcmp.h +54 -0
  80. data/ext/clipsruby/dffnxexe.c +241 -0
  81. data/ext/clipsruby/dffnxexe.h +58 -0
  82. data/ext/clipsruby/dffnxfun.c +1192 -0
  83. data/ext/clipsruby/dffnxfun.h +155 -0
  84. data/ext/clipsruby/dffnxpsr.c +514 -0
  85. data/ext/clipsruby/dffnxpsr.h +57 -0
  86. data/ext/clipsruby/dfinsbin.c +509 -0
  87. data/ext/clipsruby/dfinsbin.h +66 -0
  88. data/ext/clipsruby/dfinscmp.c +345 -0
  89. data/ext/clipsruby/dfinscmp.h +48 -0
  90. data/ext/clipsruby/drive.c +1191 -0
  91. data/ext/clipsruby/drive.h +65 -0
  92. data/ext/clipsruby/emathfun.c +1213 -0
  93. data/ext/clipsruby/emathfun.h +99 -0
  94. data/ext/clipsruby/engine.c +1568 -0
  95. data/ext/clipsruby/engine.h +203 -0
  96. data/ext/clipsruby/entities.h +276 -0
  97. data/ext/clipsruby/envrnbld.c +514 -0
  98. data/ext/clipsruby/envrnbld.h +40 -0
  99. data/ext/clipsruby/envrnmnt.c +257 -0
  100. data/ext/clipsruby/envrnmnt.h +112 -0
  101. data/ext/clipsruby/evaluatn.c +1736 -0
  102. data/ext/clipsruby/evaluatn.h +211 -0
  103. data/ext/clipsruby/expressn.c +494 -0
  104. data/ext/clipsruby/expressn.h +154 -0
  105. data/ext/clipsruby/exprnbin.c +538 -0
  106. data/ext/clipsruby/exprnbin.h +60 -0
  107. data/ext/clipsruby/exprnops.c +564 -0
  108. data/ext/clipsruby/exprnops.h +67 -0
  109. data/ext/clipsruby/exprnpsr.c +1112 -0
  110. data/ext/clipsruby/exprnpsr.h +98 -0
  111. data/ext/clipsruby/extconf.rb +2 -0
  112. data/ext/clipsruby/extnfunc.c +1015 -0
  113. data/ext/clipsruby/extnfunc.h +157 -0
  114. data/ext/clipsruby/factbin.c +447 -0
  115. data/ext/clipsruby/factbin.h +56 -0
  116. data/ext/clipsruby/factbld.c +1035 -0
  117. data/ext/clipsruby/factbld.h +63 -0
  118. data/ext/clipsruby/factcmp.c +386 -0
  119. data/ext/clipsruby/factcmp.h +46 -0
  120. data/ext/clipsruby/factcom.c +759 -0
  121. data/ext/clipsruby/factcom.h +80 -0
  122. data/ext/clipsruby/factfile.c +1761 -0
  123. data/ext/clipsruby/factfile.h +54 -0
  124. data/ext/clipsruby/factfun.c +682 -0
  125. data/ext/clipsruby/factfun.h +77 -0
  126. data/ext/clipsruby/factgen.c +1305 -0
  127. data/ext/clipsruby/factgen.h +229 -0
  128. data/ext/clipsruby/facthsh.c +438 -0
  129. data/ext/clipsruby/facthsh.h +81 -0
  130. data/ext/clipsruby/factlhs.c +250 -0
  131. data/ext/clipsruby/factlhs.h +54 -0
  132. data/ext/clipsruby/factmch.c +905 -0
  133. data/ext/clipsruby/factmch.h +68 -0
  134. data/ext/clipsruby/factmngr.c +3373 -0
  135. data/ext/clipsruby/factmngr.h +325 -0
  136. data/ext/clipsruby/factprt.c +498 -0
  137. data/ext/clipsruby/factprt.h +60 -0
  138. data/ext/clipsruby/factqpsr.c +796 -0
  139. data/ext/clipsruby/factqpsr.h +61 -0
  140. data/ext/clipsruby/factqury.c +1267 -0
  141. data/ext/clipsruby/factqury.h +112 -0
  142. data/ext/clipsruby/factrete.c +978 -0
  143. data/ext/clipsruby/factrete.h +70 -0
  144. data/ext/clipsruby/factrhs.c +667 -0
  145. data/ext/clipsruby/factrhs.h +55 -0
  146. data/ext/clipsruby/filecom.c +353 -0
  147. data/ext/clipsruby/filecom.h +137 -0
  148. data/ext/clipsruby/filertr.c +481 -0
  149. data/ext/clipsruby/filertr.h +94 -0
  150. data/ext/clipsruby/fileutil.c +1020 -0
  151. data/ext/clipsruby/fileutil.h +50 -0
  152. data/ext/clipsruby/generate.c +1079 -0
  153. data/ext/clipsruby/generate.h +57 -0
  154. data/ext/clipsruby/genrcbin.c +902 -0
  155. data/ext/clipsruby/genrcbin.h +69 -0
  156. data/ext/clipsruby/genrccmp.c +640 -0
  157. data/ext/clipsruby/genrccmp.h +59 -0
  158. data/ext/clipsruby/genrccom.c +2017 -0
  159. data/ext/clipsruby/genrccom.h +119 -0
  160. data/ext/clipsruby/genrcexe.c +737 -0
  161. data/ext/clipsruby/genrcexe.h +73 -0
  162. data/ext/clipsruby/genrcfun.c +890 -0
  163. data/ext/clipsruby/genrcfun.h +185 -0
  164. data/ext/clipsruby/genrcpsr.c +1618 -0
  165. data/ext/clipsruby/genrcpsr.h +80 -0
  166. data/ext/clipsruby/globlbin.c +458 -0
  167. data/ext/clipsruby/globlbin.h +71 -0
  168. data/ext/clipsruby/globlbsc.c +361 -0
  169. data/ext/clipsruby/globlbsc.h +83 -0
  170. data/ext/clipsruby/globlcmp.c +330 -0
  171. data/ext/clipsruby/globlcmp.h +52 -0
  172. data/ext/clipsruby/globlcom.c +289 -0
  173. data/ext/clipsruby/globlcom.h +63 -0
  174. data/ext/clipsruby/globldef.c +1087 -0
  175. data/ext/clipsruby/globldef.h +151 -0
  176. data/ext/clipsruby/globlpsr.c +530 -0
  177. data/ext/clipsruby/globlpsr.h +59 -0
  178. data/ext/clipsruby/immthpsr.c +431 -0
  179. data/ext/clipsruby/immthpsr.h +55 -0
  180. data/ext/clipsruby/incrrset.c +530 -0
  181. data/ext/clipsruby/incrrset.h +73 -0
  182. data/ext/clipsruby/inherpsr.c +850 -0
  183. data/ext/clipsruby/inherpsr.h +52 -0
  184. data/ext/clipsruby/inscom.c +2076 -0
  185. data/ext/clipsruby/inscom.h +182 -0
  186. data/ext/clipsruby/insfile.c +1764 -0
  187. data/ext/clipsruby/insfile.h +96 -0
  188. data/ext/clipsruby/insfun.c +1451 -0
  189. data/ext/clipsruby/insfun.h +134 -0
  190. data/ext/clipsruby/insmngr.c +2550 -0
  191. data/ext/clipsruby/insmngr.h +125 -0
  192. data/ext/clipsruby/insmoddp.c +1041 -0
  193. data/ext/clipsruby/insmoddp.h +91 -0
  194. data/ext/clipsruby/insmult.c +804 -0
  195. data/ext/clipsruby/insmult.h +62 -0
  196. data/ext/clipsruby/inspsr.c +602 -0
  197. data/ext/clipsruby/inspsr.h +60 -0
  198. data/ext/clipsruby/insquery.c +1278 -0
  199. data/ext/clipsruby/insquery.h +115 -0
  200. data/ext/clipsruby/insqypsr.c +729 -0
  201. data/ext/clipsruby/insqypsr.h +63 -0
  202. data/ext/clipsruby/iofun.c +2045 -0
  203. data/ext/clipsruby/iofun.h +116 -0
  204. data/ext/clipsruby/lgcldpnd.c +644 -0
  205. data/ext/clipsruby/lgcldpnd.h +75 -0
  206. data/ext/clipsruby/main.c +112 -0
  207. data/ext/clipsruby/match.h +142 -0
  208. data/ext/clipsruby/memalloc.c +481 -0
  209. data/ext/clipsruby/memalloc.h +197 -0
  210. data/ext/clipsruby/miscfun.c +1801 -0
  211. data/ext/clipsruby/miscfun.h +132 -0
  212. data/ext/clipsruby/modulbin.c +607 -0
  213. data/ext/clipsruby/modulbin.h +84 -0
  214. data/ext/clipsruby/modulbsc.c +347 -0
  215. data/ext/clipsruby/modulbsc.h +67 -0
  216. data/ext/clipsruby/modulcmp.c +499 -0
  217. data/ext/clipsruby/modulcmp.h +54 -0
  218. data/ext/clipsruby/moduldef.c +817 -0
  219. data/ext/clipsruby/moduldef.h +271 -0
  220. data/ext/clipsruby/modulpsr.c +1150 -0
  221. data/ext/clipsruby/modulpsr.h +69 -0
  222. data/ext/clipsruby/modulutl.c +1036 -0
  223. data/ext/clipsruby/modulutl.h +84 -0
  224. data/ext/clipsruby/msgcom.c +1221 -0
  225. data/ext/clipsruby/msgcom.h +125 -0
  226. data/ext/clipsruby/msgfun.c +1076 -0
  227. data/ext/clipsruby/msgfun.h +118 -0
  228. data/ext/clipsruby/msgpass.c +1441 -0
  229. data/ext/clipsruby/msgpass.h +103 -0
  230. data/ext/clipsruby/msgpsr.c +698 -0
  231. data/ext/clipsruby/msgpsr.h +73 -0
  232. data/ext/clipsruby/multifld.c +1404 -0
  233. data/ext/clipsruby/multifld.h +130 -0
  234. data/ext/clipsruby/multifun.c +2182 -0
  235. data/ext/clipsruby/multifun.h +102 -0
  236. data/ext/clipsruby/network.h +142 -0
  237. data/ext/clipsruby/objbin.c +1522 -0
  238. data/ext/clipsruby/objbin.h +79 -0
  239. data/ext/clipsruby/objcmp.c +1507 -0
  240. data/ext/clipsruby/objcmp.h +71 -0
  241. data/ext/clipsruby/object.h +260 -0
  242. data/ext/clipsruby/objrtbin.c +701 -0
  243. data/ext/clipsruby/objrtbin.h +79 -0
  244. data/ext/clipsruby/objrtbld.c +2393 -0
  245. data/ext/clipsruby/objrtbld.h +66 -0
  246. data/ext/clipsruby/objrtcmp.c +734 -0
  247. data/ext/clipsruby/objrtcmp.h +66 -0
  248. data/ext/clipsruby/objrtfnx.c +1330 -0
  249. data/ext/clipsruby/objrtfnx.h +222 -0
  250. data/ext/clipsruby/objrtgen.c +736 -0
  251. data/ext/clipsruby/objrtgen.h +63 -0
  252. data/ext/clipsruby/objrtmch.c +1524 -0
  253. data/ext/clipsruby/objrtmch.h +160 -0
  254. data/ext/clipsruby/parsefun.c +415 -0
  255. data/ext/clipsruby/parsefun.h +67 -0
  256. data/ext/clipsruby/pattern.c +1265 -0
  257. data/ext/clipsruby/pattern.h +163 -0
  258. data/ext/clipsruby/pprint.c +328 -0
  259. data/ext/clipsruby/pprint.h +79 -0
  260. data/ext/clipsruby/prccode.c +1478 -0
  261. data/ext/clipsruby/prccode.h +145 -0
  262. data/ext/clipsruby/prcdrfun.c +640 -0
  263. data/ext/clipsruby/prcdrfun.h +95 -0
  264. data/ext/clipsruby/prcdrpsr.c +1068 -0
  265. data/ext/clipsruby/prcdrpsr.h +79 -0
  266. data/ext/clipsruby/prdctfun.c +869 -0
  267. data/ext/clipsruby/prdctfun.h +77 -0
  268. data/ext/clipsruby/prntutil.c +878 -0
  269. data/ext/clipsruby/prntutil.h +125 -0
  270. data/ext/clipsruby/proflfun.c +827 -0
  271. data/ext/clipsruby/proflfun.h +118 -0
  272. data/ext/clipsruby/reorder.c +2082 -0
  273. data/ext/clipsruby/reorder.h +172 -0
  274. data/ext/clipsruby/reteutil.c +1732 -0
  275. data/ext/clipsruby/reteutil.h +111 -0
  276. data/ext/clipsruby/retract.c +710 -0
  277. data/ext/clipsruby/retract.h +74 -0
  278. data/ext/clipsruby/router.c +737 -0
  279. data/ext/clipsruby/router.h +147 -0
  280. data/ext/clipsruby/rulebin.c +1136 -0
  281. data/ext/clipsruby/rulebin.h +153 -0
  282. data/ext/clipsruby/rulebld.c +1328 -0
  283. data/ext/clipsruby/rulebld.h +62 -0
  284. data/ext/clipsruby/rulebsc.c +517 -0
  285. data/ext/clipsruby/rulebsc.h +91 -0
  286. data/ext/clipsruby/rulecmp.c +733 -0
  287. data/ext/clipsruby/rulecmp.h +63 -0
  288. data/ext/clipsruby/rulecom.c +1583 -0
  289. data/ext/clipsruby/rulecom.h +116 -0
  290. data/ext/clipsruby/rulecstr.c +892 -0
  291. data/ext/clipsruby/rulecstr.h +53 -0
  292. data/ext/clipsruby/ruledef.c +559 -0
  293. data/ext/clipsruby/ruledef.h +179 -0
  294. data/ext/clipsruby/ruledlt.c +599 -0
  295. data/ext/clipsruby/ruledlt.h +58 -0
  296. data/ext/clipsruby/rulelhs.c +1216 -0
  297. data/ext/clipsruby/rulelhs.h +52 -0
  298. data/ext/clipsruby/rulepsr.c +1073 -0
  299. data/ext/clipsruby/rulepsr.h +61 -0
  300. data/ext/clipsruby/scanner.c +856 -0
  301. data/ext/clipsruby/scanner.h +112 -0
  302. data/ext/clipsruby/setup.h +488 -0
  303. data/ext/clipsruby/sortfun.c +433 -0
  304. data/ext/clipsruby/sortfun.h +55 -0
  305. data/ext/clipsruby/strngfun.c +1173 -0
  306. data/ext/clipsruby/strngfun.h +96 -0
  307. data/ext/clipsruby/strngrtr.c +523 -0
  308. data/ext/clipsruby/strngrtr.h +97 -0
  309. data/ext/clipsruby/symblbin.c +648 -0
  310. data/ext/clipsruby/symblbin.h +64 -0
  311. data/ext/clipsruby/symblcmp.c +893 -0
  312. data/ext/clipsruby/symblcmp.h +61 -0
  313. data/ext/clipsruby/symbol.c +1961 -0
  314. data/ext/clipsruby/symbol.h +243 -0
  315. data/ext/clipsruby/sysdep.c +894 -0
  316. data/ext/clipsruby/sysdep.h +164 -0
  317. data/ext/clipsruby/textpro.c +1388 -0
  318. data/ext/clipsruby/textpro.h +77 -0
  319. data/ext/clipsruby/tmpltbin.c +609 -0
  320. data/ext/clipsruby/tmpltbin.h +108 -0
  321. data/ext/clipsruby/tmpltbsc.c +327 -0
  322. data/ext/clipsruby/tmpltbsc.h +87 -0
  323. data/ext/clipsruby/tmpltcmp.c +450 -0
  324. data/ext/clipsruby/tmpltcmp.h +57 -0
  325. data/ext/clipsruby/tmpltdef.c +584 -0
  326. data/ext/clipsruby/tmpltdef.h +155 -0
  327. data/ext/clipsruby/tmpltfun.c +2477 -0
  328. data/ext/clipsruby/tmpltfun.h +122 -0
  329. data/ext/clipsruby/tmpltlhs.c +379 -0
  330. data/ext/clipsruby/tmpltlhs.h +50 -0
  331. data/ext/clipsruby/tmpltpsr.c +819 -0
  332. data/ext/clipsruby/tmpltpsr.h +59 -0
  333. data/ext/clipsruby/tmpltrhs.c +595 -0
  334. data/ext/clipsruby/tmpltrhs.h +55 -0
  335. data/ext/clipsruby/tmpltutl.c +637 -0
  336. data/ext/clipsruby/tmpltutl.h +82 -0
  337. data/ext/clipsruby/userdata.c +156 -0
  338. data/ext/clipsruby/userdata.h +72 -0
  339. data/ext/clipsruby/userfunctions.c +70 -0
  340. data/ext/clipsruby/usrsetup.h +7 -0
  341. data/ext/clipsruby/utility.c +1594 -0
  342. data/ext/clipsruby/utility.h +250 -0
  343. data/ext/clipsruby/watch.c +865 -0
  344. data/ext/clipsruby/watch.h +124 -0
  345. data/lib/clipsruby.rb +1 -0
  346. metadata +388 -0
@@ -0,0 +1,2393 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 02/03/21 */
5
+ /* */
6
+ /* OBJECT PATTERN MATCHER MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: RETE Network Parsing Interface for Objects */
11
+ /* */
12
+ /* Principal Programmer(s): */
13
+ /* Brian L. Dantes */
14
+ /* */
15
+ /* Contributing Programmer(s): */
16
+ /* */
17
+ /* Revision History: */
18
+ /* */
19
+ /* 6.24: Removed INCREMENTAL_RESET compilation flag. */
20
+ /* */
21
+ /* Converted INSTANCE_PATTERN_MATCHING to */
22
+ /* DEFRULE_CONSTRUCT. */
23
+ /* */
24
+ /* Renamed BOOLEAN macro type to intBool. */
25
+ /* */
26
+ /* 6.30: Changed integer type/precision. */
27
+ /* */
28
+ /* Removed conditional code for unsupported */
29
+ /* compilers/operating systems (IBM_MCW, */
30
+ /* MAC_MCW, and IBM_TBC). */
31
+ /* */
32
+ /* Support for long long integers. */
33
+ /* */
34
+ /* Added support for hashed comparisons to */
35
+ /* constants. */
36
+ /* */
37
+ /* Added support for hashed alpha memories. */
38
+ /* */
39
+ /* Added const qualifiers to remove C++ */
40
+ /* deprecation warnings. */
41
+ /* */
42
+ /* 6.31: Added class name to OBJRTBLD5 error message. */
43
+ /* */
44
+ /* Optimization for marking relevant alpha nodes */
45
+ /* in the object pattern network. */
46
+ /* */
47
+ /* 6.40: Pragma once and other inclusion changes. */
48
+ /* */
49
+ /* Added support for booleans with <stdbool.h>. */
50
+ /* */
51
+ /* Removed use of void pointers for specific */
52
+ /* data structures. */
53
+ /* */
54
+ /* Static constraint checking is always enabled. */
55
+ /* */
56
+ /* UDF redesign. */
57
+ /* */
58
+ /* Removed initial-object support. */
59
+ /* */
60
+ /*************************************************************/
61
+ /* =========================================
62
+ *****************************************
63
+ EXTERNAL DEFINITIONS
64
+ =========================================
65
+ ***************************************** */
66
+ #include "setup.h"
67
+
68
+ #if DEFRULE_CONSTRUCT && OBJECT_SYSTEM
69
+
70
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
71
+
72
+ #include <string.h>
73
+ #include <stdlib.h>
74
+
75
+ #include "classcom.h"
76
+ #include "classfun.h"
77
+ #include "cstrnutl.h"
78
+ #include "constrnt.h"
79
+ #include "cstrnchk.h"
80
+ #include "cstrnops.h"
81
+ #include "drive.h"
82
+ #include "envrnmnt.h"
83
+ #include "inscom.h"
84
+ #include "insfun.h"
85
+ #include "insmngr.h"
86
+ #include "memalloc.h"
87
+ #include "network.h"
88
+ #include "object.h"
89
+ #include "pattern.h"
90
+ #include "prntutil.h"
91
+ #include "reteutil.h"
92
+ #include "ruledef.h"
93
+ #include "rulepsr.h"
94
+ #include "scanner.h"
95
+ #include "symbol.h"
96
+ #include "utility.h"
97
+
98
+ #endif
99
+
100
+ #include "constrct.h"
101
+ #include "exprnpsr.h"
102
+ #include "objrtmch.h"
103
+ #include "objrtgen.h"
104
+ #include "objrtfnx.h"
105
+ #include "pprint.h"
106
+ #include "reorder.h"
107
+ #include "router.h"
108
+
109
+ #if BLOAD_AND_BSAVE || BLOAD || BLOAD_ONLY
110
+ #include "objrtbin.h"
111
+ #endif
112
+
113
+ #if CONSTRUCT_COMPILER && (! RUN_TIME)
114
+ #include "objrtcmp.h"
115
+ #endif
116
+
117
+ #include "objrtbld.h"
118
+
119
+ #if ! DEFINSTANCES_CONSTRUCT
120
+ #include "classfun.h"
121
+ #include "classcom.h"
122
+ #include "extnfunc.h"
123
+ #endif
124
+
125
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
126
+
127
+ /* =========================================
128
+ *****************************************
129
+ CONSTANTS
130
+ =========================================
131
+ ***************************************** */
132
+ #define OBJECT_PATTERN_INDICATOR "object"
133
+
134
+ /* =========================================
135
+ *****************************************
136
+ INTERNALLY VISIBLE FUNCTION HEADERS
137
+ =========================================
138
+ ***************************************** */
139
+
140
+ static bool PatternParserFind(CLIPSLexeme *);
141
+ static struct lhsParseNode *ObjectLHSParse(Environment *,const char *,struct token *);
142
+ static bool ReorderAndAnalyzeObjectPattern(Environment *,struct lhsParseNode *);
143
+ static struct patternNodeHeader
144
+ *PlaceObjectPattern(Environment *,struct lhsParseNode *);
145
+ static OBJECT_PATTERN_NODE *FindObjectPatternNode(OBJECT_PATTERN_NODE *,struct lhsParseNode *,
146
+ OBJECT_PATTERN_NODE **,bool,bool);
147
+ static OBJECT_PATTERN_NODE *CreateNewObjectPatternNode(Environment *,struct lhsParseNode *,OBJECT_PATTERN_NODE *,
148
+ OBJECT_PATTERN_NODE *,bool,bool);
149
+ static void DetachObjectPattern(Environment *,struct patternNodeHeader *);
150
+ static void ClearObjectPatternMatches(Environment *,OBJECT_ALPHA_NODE *);
151
+ static void RemoveObjectPartialMatches(Environment *,Instance *,struct patternNodeHeader *);
152
+ static bool CheckDuplicateSlots(Environment *,struct lhsParseNode *,CLIPSLexeme *);
153
+ static struct lhsParseNode *ParseClassRestriction(Environment *,const char *,struct token *);
154
+ static struct lhsParseNode *ParseNameRestriction(Environment *,const char *,struct token *);
155
+ static struct lhsParseNode *ParseSlotRestriction(Environment *,const char *,struct token *,CONSTRAINT_RECORD *,bool);
156
+ static CLASS_BITMAP *NewClassBitMap(Environment *,unsigned short,bool);
157
+ static void InitializeClassBitMap(Environment *,CLASS_BITMAP *,bool);
158
+ static void DeleteIntermediateClassBitMap(Environment *,const CLASS_BITMAP *);
159
+ static void *CopyClassBitMap(Environment *,void *);
160
+ static void DeleteClassBitMap(Environment *,void *);
161
+ static void MarkBitMapClassesBusy(Environment *,CLIPSBitMap *,int);
162
+ static bool EmptyClassBitMap(CLASS_BITMAP *);
163
+ static bool IdenticalClassBitMap(const CLASS_BITMAP *,const CLASS_BITMAP *);
164
+ static bool ProcessClassRestriction(Environment *,CLASS_BITMAP *,struct lhsParseNode **,bool);
165
+ static CONSTRAINT_RECORD *ProcessSlotRestriction(Environment *,CLASS_BITMAP *,CLIPSLexeme *,bool *);
166
+ static void IntersectClassBitMaps(CLASS_BITMAP *,CLASS_BITMAP *);
167
+ static void UnionClassBitMaps(CLASS_BITMAP *,CLASS_BITMAP *);
168
+ static CLASS_BITMAP *PackClassBitMap(Environment *,CLASS_BITMAP *);
169
+ static struct lhsParseNode *FilterObjectPattern(Environment *,struct patternParser *,
170
+ struct lhsParseNode *,struct lhsParseNode **,
171
+ struct lhsParseNode **,struct lhsParseNode **);
172
+ static CLIPSBitMap *FormSlotBitMap(Environment *,struct lhsParseNode *);
173
+ static struct lhsParseNode *RemoveSlotExistenceTests(Environment *,struct lhsParseNode *,CLIPSBitMap **);
174
+ static void MarkObjectPtnIncrementalReset(Environment *,struct patternNodeHeader *,bool);
175
+ static void ObjectIncrementalReset(Environment *);
176
+
177
+ #endif
178
+
179
+ static Expression *ObjectMatchDelayParse(Environment *,Expression *,const char *);
180
+
181
+ /* =========================================
182
+ *****************************************
183
+ EXTERNALLY VISIBLE FUNCTIONS
184
+ =========================================
185
+ ***************************************** */
186
+
187
+ /********************************************************
188
+ NAME : SetupObjectPatternStuff
189
+ DESCRIPTION : Installs the parsers and other items
190
+ necessary for recognizing and processing
191
+ object patterns in defrules
192
+ INPUTS : None
193
+ RETURNS : Nothing useful
194
+ SIDE EFFECTS : Rete network interfaces for objects
195
+ initialized
196
+ NOTES : None
197
+ ********************************************************/
198
+ void SetupObjectPatternStuff(
199
+ Environment *theEnv)
200
+ {
201
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
202
+ struct patternParser *newPtr;
203
+
204
+ if (ReservedPatternSymbol(theEnv,"object",NULL) == true)
205
+ {
206
+ SystemError(theEnv,"OBJRTBLD",1);
207
+ ExitRouter(theEnv,EXIT_FAILURE);
208
+ }
209
+ AddReservedPatternSymbol(theEnv,"object",NULL);
210
+
211
+ /* ===========================================================================
212
+ The object pattern parser needs to have a higher priority than deftemplates
213
+ or regular facts so that the "object" keyword is always recognized first
214
+ =========================================================================== */
215
+
216
+ newPtr = get_struct(theEnv,patternParser);
217
+
218
+ newPtr->name = "objects";
219
+ newPtr->priority = 20;
220
+ newPtr->entityType = &InstanceData(theEnv)->InstanceInfo;
221
+
222
+ newPtr->recognizeFunction = PatternParserFind;
223
+ newPtr->parseFunction = ObjectLHSParse;
224
+ newPtr->postAnalysisFunction = ReorderAndAnalyzeObjectPattern;
225
+ newPtr->addPatternFunction = PlaceObjectPattern;
226
+ newPtr->removePatternFunction = DetachObjectPattern;
227
+ newPtr->genJNConstantFunction = NULL;
228
+ newPtr->replaceGetJNValueFunction = ReplaceGetJNObjectValue;
229
+ newPtr->genGetJNValueFunction = GenGetJNObjectValue;
230
+ newPtr->genCompareJNValuesFunction = ObjectJNVariableComparison;
231
+ newPtr->genPNConstantFunction = GenObjectPNConstantCompare;
232
+ newPtr->replaceGetPNValueFunction = ReplaceGetPNObjectValue;
233
+ newPtr->genGetPNValueFunction = GenGetPNObjectValue;
234
+ newPtr->genComparePNValuesFunction = ObjectPNVariableComparison;
235
+ newPtr->returnUserDataFunction = DeleteClassBitMap;
236
+ newPtr->copyUserDataFunction = CopyClassBitMap;
237
+
238
+ newPtr->markIRPatternFunction = MarkObjectPtnIncrementalReset;
239
+ newPtr->incrementalResetFunction = ObjectIncrementalReset;
240
+
241
+ #if CONSTRUCT_COMPILER && (! RUN_TIME)
242
+ newPtr->codeReferenceFunction = ObjectPatternNodeReference;
243
+ #else
244
+ newPtr->codeReferenceFunction = NULL;
245
+ #endif
246
+
247
+ AddPatternParser(theEnv,newPtr);
248
+
249
+ #endif
250
+
251
+ #if (! RUN_TIME)
252
+ AddUDF(theEnv,"object-pattern-match-delay","*",0,UNBOUNDED,NULL,ObjectMatchDelay,"ObjectMatchDelay",NULL);
253
+ FuncSeqOvlFlags(theEnv,"object-pattern-match-delay",false,false);
254
+ #endif
255
+
256
+ AddFunctionParser(theEnv,"object-pattern-match-delay",ObjectMatchDelayParse);
257
+
258
+ InstallObjectPrimitives(theEnv);
259
+
260
+ #if CONSTRUCT_COMPILER && (! RUN_TIME)
261
+ ObjectPatternsCompilerSetup(theEnv);
262
+ #endif
263
+
264
+ #if BLOAD_AND_BSAVE || BLOAD || BLOAD_ONLY
265
+ SetupObjectPatternsBload(theEnv);
266
+ #endif
267
+ }
268
+
269
+ /* =========================================
270
+ *****************************************
271
+ INTERNALLY VISIBLE FUNCTIONS
272
+ =========================================
273
+ ***************************************** */
274
+
275
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
276
+
277
+ /*****************************************************
278
+ NAME : PatternParserFind
279
+ DESCRIPTION : Determines if a pattern CE is an
280
+ object pattern (i.e. the first field
281
+ is the constant symbol "object")
282
+ INPUTS : 1) The type of the first field
283
+ 2) The value of the first field
284
+ RETURNS : True if it is an object pattern,
285
+ false otherwise
286
+ SIDE EFFECTS : None
287
+ NOTES : Used by AddPatternParser()
288
+ *****************************************************/
289
+ static bool PatternParserFind(
290
+ CLIPSLexeme *value)
291
+ {
292
+ if (strcmp(value->contents,OBJECT_PATTERN_INDICATOR) == 0)
293
+ return true;
294
+
295
+ return false;
296
+ }
297
+
298
+ /************************************************************************************
299
+ NAME : ObjectLHSParse
300
+ DESCRIPTION : Scans and parses an object pattern for a rule
301
+ INPUTS : 1) The logical name of the input source
302
+ 2) A buffer holding the last token read
303
+ RETURNS : The address of struct lhsParseNodes, NULL on errors
304
+ SIDE EFFECTS : A series of struct lhsParseNodes are created to represent
305
+ the intermediate parse of the pattern
306
+ Pretty-print form for the pattern is saved
307
+ NOTES : Object Pattern Syntax:
308
+ (object [<class-constraint>] [<name-constraint>] <slot-constraint>*)
309
+ <class-constraint> ::= (is-a <constraint>)
310
+ <name-constraint> ::= (name <constraint>)
311
+ <slot-constraint> ::= (<slot-name> <constraint>*)
312
+ ************************************************************************************/
313
+ static struct lhsParseNode *ObjectLHSParse(
314
+ Environment *theEnv,
315
+ const char *readSource,
316
+ struct token *lastToken)
317
+ {
318
+ #if MAC_XCD
319
+ #pragma unused(lastToken)
320
+ #endif
321
+ struct token theToken;
322
+ struct lhsParseNode *firstNode = NULL,*lastNode = NULL,*tmpNode;
323
+ CLASS_BITMAP *clsset,*tmpset;
324
+ CONSTRAINT_RECORD *slotConstraints;
325
+ bool ppbackupReqd = false,multip;
326
+
327
+ /* ========================================================
328
+ Get a bitmap big enough to mark the ids of all currently
329
+ existing classes - and set all bits, since the initial
330
+ set of applicable classes is everything.
331
+ ======================================================== */
332
+ clsset = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,true);
333
+ if (EmptyClassBitMap(clsset))
334
+ {
335
+ PrintErrorID(theEnv,"OBJRTBLD",1,false);
336
+ WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern.\n");
337
+ DeleteIntermediateClassBitMap(theEnv,clsset);
338
+ return NULL;
339
+ }
340
+ tmpset = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,true);
341
+
342
+ IncrementIndentDepth(theEnv,7);
343
+
344
+ /* ===========================================
345
+ Parse the class, name and slot restrictions
346
+ =========================================== */
347
+ GetToken(theEnv,readSource,&theToken);
348
+ while (theToken.tknType != RIGHT_PARENTHESIS_TOKEN)
349
+ {
350
+ ppbackupReqd = true;
351
+ PPBackup(theEnv);
352
+ SavePPBuffer(theEnv," ");
353
+ SavePPBuffer(theEnv,theToken.printForm);
354
+ if (theToken.tknType != LEFT_PARENTHESIS_TOKEN)
355
+ {
356
+ SyntaxErrorMessage(theEnv,"object pattern");
357
+ goto ObjectLHSParseERROR;
358
+ }
359
+ GetToken(theEnv,readSource,&theToken);
360
+ if (theToken.tknType != SYMBOL_TOKEN)
361
+ {
362
+ SyntaxErrorMessage(theEnv,"object pattern");
363
+ goto ObjectLHSParseERROR;
364
+ }
365
+ if (CheckDuplicateSlots(theEnv,firstNode,theToken.lexemeValue))
366
+ goto ObjectLHSParseERROR;
367
+ if (theToken.value == (void *) DefclassData(theEnv)->ISA_SYMBOL)
368
+ {
369
+ tmpNode = ParseClassRestriction(theEnv,readSource,&theToken);
370
+ if (tmpNode == NULL)
371
+ goto ObjectLHSParseERROR;
372
+ InitializeClassBitMap(theEnv,tmpset,false);
373
+ if (ProcessClassRestriction(theEnv,tmpset,&tmpNode->bottom,true) == false)
374
+ {
375
+ ReturnLHSParseNodes(theEnv,tmpNode);
376
+ goto ObjectLHSParseERROR;
377
+ }
378
+ IntersectClassBitMaps(clsset,tmpset);
379
+ }
380
+ else if (theToken.value == (void *) DefclassData(theEnv)->NAME_SYMBOL)
381
+ {
382
+ tmpNode = ParseNameRestriction(theEnv,readSource,&theToken);
383
+ if (tmpNode == NULL)
384
+ goto ObjectLHSParseERROR;
385
+ InitializeClassBitMap(theEnv,tmpset,true);
386
+ }
387
+ else
388
+ {
389
+ slotConstraints = ProcessSlotRestriction(theEnv,clsset,theToken.lexemeValue,&multip);
390
+ if (slotConstraints != NULL)
391
+ {
392
+ InitializeClassBitMap(theEnv,tmpset,true);
393
+ tmpNode = ParseSlotRestriction(theEnv,readSource,&theToken,slotConstraints,multip);
394
+ if (tmpNode == NULL)
395
+ goto ObjectLHSParseERROR;
396
+ }
397
+ else
398
+ {
399
+ InitializeClassBitMap(theEnv,tmpset,false);
400
+ tmpNode = GetLHSParseNode(theEnv);
401
+ tmpNode->slot = theToken.lexemeValue;
402
+ }
403
+ }
404
+ if (EmptyClassBitMap(tmpset))
405
+ {
406
+ PrintErrorID(theEnv,"OBJRTBLD",2,false);
407
+ WriteString(theEnv,STDERR,"No objects of existing classes can satisfy '");
408
+ WriteString(theEnv,STDERR,tmpNode->slot->contents);
409
+ WriteString(theEnv,STDERR,"' restriction in object pattern.\n");
410
+ ReturnLHSParseNodes(theEnv,tmpNode);
411
+ goto ObjectLHSParseERROR;
412
+ }
413
+ if (EmptyClassBitMap(clsset))
414
+ {
415
+ PrintErrorID(theEnv,"OBJRTBLD",1,false);
416
+ WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern.\n");
417
+ ReturnLHSParseNodes(theEnv,tmpNode);
418
+ goto ObjectLHSParseERROR;
419
+ }
420
+ if (tmpNode != NULL)
421
+ {
422
+ if (firstNode == NULL)
423
+ firstNode = tmpNode;
424
+ else
425
+ lastNode->right = tmpNode;
426
+ lastNode = tmpNode;
427
+ }
428
+ PPCRAndIndent(theEnv);
429
+ GetToken(theEnv,readSource,&theToken);
430
+ }
431
+ if (firstNode == NULL)
432
+ {
433
+ if (EmptyClassBitMap(clsset))
434
+ {
435
+ PrintErrorID(theEnv,"OBJRTBLD",1,false);
436
+ WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern.\n");
437
+ goto ObjectLHSParseERROR;
438
+ }
439
+ firstNode = GetLHSParseNode(theEnv);
440
+ firstNode->pnType = SF_WILDCARD_NODE;
441
+ firstNode->slot = DefclassData(theEnv)->ISA_SYMBOL;
442
+ firstNode->slotNumber = ISA_ID;
443
+ firstNode->index = 1;
444
+ }
445
+ if (ppbackupReqd)
446
+ {
447
+ PPBackup(theEnv);
448
+ PPBackup(theEnv);
449
+ SavePPBuffer(theEnv,theToken.printForm);
450
+ }
451
+ DeleteIntermediateClassBitMap(theEnv,tmpset);
452
+ clsset = PackClassBitMap(theEnv,clsset);
453
+ firstNode->userData = AddBitMap(theEnv,clsset,ClassBitMapSize(clsset));
454
+ IncrementBitMapCount(firstNode->userData);
455
+ DeleteIntermediateClassBitMap(theEnv,clsset);
456
+ DecrementIndentDepth(theEnv,7);
457
+ return(firstNode);
458
+
459
+ ObjectLHSParseERROR:
460
+ DeleteIntermediateClassBitMap(theEnv,clsset);
461
+ DeleteIntermediateClassBitMap(theEnv,tmpset);
462
+ ReturnLHSParseNodes(theEnv,firstNode);
463
+ DecrementIndentDepth(theEnv,7);
464
+ return NULL;
465
+ }
466
+
467
+ /**************************************************************
468
+ NAME : ReorderAndAnalyzeObjectPattern
469
+ DESCRIPTION : This function reexamines the object pattern
470
+ after constraint and variable analysis info
471
+ has been propagated from other patterns.
472
+ Any slots which are no longer applicable
473
+ to the pattern are eliminated from the
474
+ class set.
475
+ Also, the slot names are ordered according
476
+ to lexical value to aid in deteterming
477
+ sharing between object patterns. (The is-a
478
+ and name restrictions are always placed
479
+ first regardless of symbolic hash value.)
480
+ INPUTS : The pattern CE lhsParseNode
481
+ RETURNS : False if all OK, otherwise true
482
+ (e.g. all classes are eliminated as potential
483
+ matching candidates for the pattern)
484
+ SIDE EFFECTS : Slot restrictions are reordered (if necessary)
485
+ NOTES : Adds a default is-a slot if one does not
486
+ already exist
487
+ **************************************************************/
488
+ static bool ReorderAndAnalyzeObjectPattern(
489
+ Environment *theEnv,
490
+ struct lhsParseNode *topNode)
491
+ {
492
+ const CLASS_BITMAP *clsset;
493
+ CLASS_BITMAP *tmpset;
494
+ Expression *rexp,*tmpmin,*tmpmax;
495
+ Defclass *cls;
496
+ struct lhsParseNode *tmpNode,*subNode,*bitmap_node,*isa_node,*name_node;
497
+ unsigned short i;
498
+ SlotDescriptor *sd;
499
+ CONSTRAINT_RECORD *crossConstraints, *theConstraint;
500
+ int incompatibleConstraint;
501
+ bool clssetChanged = false;
502
+
503
+ /* ==========================================================
504
+ Make sure that the bitmap marking which classes of object
505
+ can match the pattern is attached to the class restriction
506
+ (which will always be present and the last restriction
507
+ after the sort)
508
+ ========================================================== */
509
+ topNode->right = FilterObjectPattern(theEnv,topNode->patternType,topNode->right,
510
+ &bitmap_node,&isa_node,&name_node);
511
+
512
+ /* ============================================
513
+ Allocate a temporary set for marking classes
514
+ ============================================ */
515
+ clsset = (const CLASS_BITMAP *) ((CLIPSBitMap *) bitmap_node->userData)->contents;
516
+ tmpset = NewClassBitMap(theEnv,clsset->maxid,false);
517
+
518
+ /* ==========================================================
519
+ Check the allowed-values for the constraint on the is-a
520
+ slot. If there are any, make sure that only the classes
521
+ with those values as names are marked in the bitmap.
522
+
523
+ There will only be symbols in the list because the
524
+ original constraint on the is-a slot allowed only symbols.
525
+ ========================================================== */
526
+ if ((isa_node == NULL) ? false :
527
+ ((isa_node->constraints == NULL) ? false :
528
+ (isa_node->constraints->restrictionList != NULL)))
529
+ {
530
+ rexp = isa_node->constraints->restrictionList;
531
+ while (rexp != NULL)
532
+ {
533
+ cls = LookupDefclassInScope(theEnv,rexp->lexemeValue->contents);
534
+ if (cls != NULL)
535
+ {
536
+ if ((cls->id <= clsset->maxid) ? TestBitMap(clsset->map,cls->id) : false)
537
+ SetBitMap(tmpset->map,cls->id);
538
+ }
539
+ rexp = rexp->nextArg;
540
+ }
541
+ clssetChanged = IdenticalClassBitMap(tmpset,clsset) ? false : true;
542
+ }
543
+ else
544
+ GenCopyMemory(char,tmpset->maxid / BITS_PER_BYTE + 1,tmpset->map,clsset->map);
545
+
546
+ /* ================================================================
547
+ For each of the slots (excluding name and is-a), check the total
548
+ constraints for the slot against the individual constraints
549
+ for each occurrence of the slot in the classes marked in
550
+ the bitmap. For any slot which is not compatible with
551
+ the overall constraint, clear its class's bit in the bitmap.
552
+ ================================================================ */
553
+ tmpNode = topNode->right;
554
+ while (tmpNode != bitmap_node)
555
+ {
556
+ if ((tmpNode == isa_node) || (tmpNode == name_node))
557
+ {
558
+ tmpNode = tmpNode->right;
559
+ continue;
560
+ }
561
+ for (i = 0 ; i <= tmpset->maxid ; i++)
562
+ if (TestBitMap(tmpset->map,i))
563
+ {
564
+ cls = DefclassData(theEnv)->ClassIDMap[i];
565
+ sd = cls->instanceTemplate[FindInstanceTemplateSlot(theEnv,cls,tmpNode->slot)];
566
+
567
+ /* =========================================
568
+ Check the top-level lhsParseNode for type
569
+ and cardinality compatibility
570
+ ========================================= */
571
+ crossConstraints = IntersectConstraints(theEnv,tmpNode->constraints,sd->constraint);
572
+ incompatibleConstraint = UnmatchableConstraint(crossConstraints);
573
+ RemoveConstraint(theEnv,crossConstraints);
574
+ if (incompatibleConstraint)
575
+ {
576
+ ClearBitMap(tmpset->map,i);
577
+ clssetChanged = true;
578
+ }
579
+ else if (tmpNode->pnType == MF_WILDCARD_NODE)
580
+ {
581
+ /* ==========================================
582
+ Check the sub-nodes for type compatibility
583
+ ========================================== */
584
+ for (subNode = tmpNode->bottom ; subNode != NULL ; subNode = subNode->right)
585
+ {
586
+ /* ========================================================
587
+ Temporarily reset cardinality of variables to
588
+ match slot so that no cardinality errors will be flagged
589
+ ======================================================== */
590
+ if ((subNode->pnType == MF_WILDCARD_NODE) || (subNode->pnType == MF_VARIABLE_NODE))
591
+ { theConstraint = subNode->constraints->multifield; }
592
+ else
593
+ { theConstraint = subNode->constraints; }
594
+
595
+ tmpmin = theConstraint->minFields;
596
+ theConstraint->minFields = sd->constraint->minFields;
597
+ tmpmax = theConstraint->maxFields;
598
+ theConstraint->maxFields = sd->constraint->maxFields;
599
+ crossConstraints = IntersectConstraints(theEnv,theConstraint,sd->constraint);
600
+ theConstraint->minFields = tmpmin;
601
+ theConstraint->maxFields = tmpmax;
602
+
603
+ incompatibleConstraint = UnmatchableConstraint(crossConstraints);
604
+ RemoveConstraint(theEnv,crossConstraints);
605
+ if (incompatibleConstraint)
606
+ {
607
+ ClearBitMap(tmpset->map,i);
608
+ clssetChanged = true;
609
+ break;
610
+ }
611
+ }
612
+ }
613
+ }
614
+ tmpNode = tmpNode->right;
615
+ }
616
+
617
+ if (clssetChanged)
618
+ {
619
+ /* =======================================================
620
+ Make sure that there are still classes of objects which
621
+ can satisfy this pattern. Otherwise, signal an error.
622
+ ======================================================= */
623
+ if (EmptyClassBitMap(tmpset))
624
+ {
625
+ PrintErrorID(theEnv,"OBJRTBLD",3,true);
626
+ DeleteIntermediateClassBitMap(theEnv,tmpset);
627
+ WriteString(theEnv,STDERR,"No objects of existing classes can satisfy pattern #");
628
+ WriteInteger(theEnv,STDERR,topNode->pattern);
629
+ WriteString(theEnv,STDERR,".\n");
630
+ return true;
631
+ }
632
+ clsset = PackClassBitMap(theEnv,tmpset);
633
+ DeleteClassBitMap(theEnv,bitmap_node->userData);
634
+ bitmap_node->userData = AddBitMap(theEnv,(void *) clsset,ClassBitMapSize(clsset));
635
+ IncrementBitMapCount(bitmap_node->userData);
636
+ DeleteIntermediateClassBitMap(theEnv,clsset);
637
+ }
638
+ else
639
+ DeleteIntermediateClassBitMap(theEnv,tmpset);
640
+ return false;
641
+ }
642
+
643
+ /*****************************************************
644
+ NAME : PlaceObjectPattern
645
+ DESCRIPTION : Integrates an object pattern into the
646
+ object pattern network
647
+ INPUTS : The intermediate parse representation
648
+ of the pattern
649
+ RETURNS : The address of the new pattern
650
+ SIDE EFFECTS : Object pattern network updated
651
+ NOTES : None
652
+ *****************************************************/
653
+ static struct patternNodeHeader *PlaceObjectPattern(
654
+ Environment *theEnv,
655
+ struct lhsParseNode *thePattern)
656
+ {
657
+ OBJECT_PATTERN_NODE *currentLevel,*lastLevel;
658
+ struct lhsParseNode *tempPattern = NULL;
659
+ OBJECT_PATTERN_NODE *nodeSlotGroup, *newNode;
660
+ OBJECT_ALPHA_NODE *newAlphaNode;
661
+ bool endSlot;
662
+ CLIPSBitMap *newClassBitMap,*newSlotBitMap;
663
+ struct expr *rightHash;
664
+ unsigned int i;
665
+ const CLASS_BITMAP *cbmp;
666
+ Defclass *relevantDefclass;
667
+ CLASS_ALPHA_LINK *newAlphaLink;
668
+
669
+ /*========================================================*/
670
+ /* Get the top of the object pattern network and prepare */
671
+ /* for the traversal to look for shareable pattern nodes. */
672
+ /*========================================================*/
673
+
674
+ currentLevel = ObjectNetworkPointer(theEnv);
675
+ lastLevel = NULL;
676
+
677
+ /*====================================================*/
678
+ /* Remove slot existence tests from the pattern since */
679
+ /* these are accounted for by the class bitmap and */
680
+ /* find the class and slot bitmaps. */
681
+ /*====================================================*/
682
+
683
+ rightHash = thePattern->rightHash;
684
+
685
+ newSlotBitMap = FormSlotBitMap(theEnv,thePattern->right);
686
+ thePattern->right = RemoveSlotExistenceTests(theEnv,thePattern->right,&newClassBitMap);
687
+ thePattern = thePattern->right;
688
+
689
+ /*=========================================================*/
690
+ /* Loop until all fields in the pattern have been added to */
691
+ /* the pattern network. Process the bitmap node ONLY if it */
692
+ /* is the only node in the pattern. */
693
+ /*=========================================================*/
694
+
695
+ do
696
+ {
697
+ if (thePattern->multifieldSlot)
698
+ {
699
+ tempPattern = thePattern;
700
+ thePattern = thePattern->bottom;
701
+ }
702
+
703
+ /*============================================*/
704
+ /* Determine if the last pattern field within */
705
+ /* a multifield slot is being processed. */
706
+ /*============================================*/
707
+
708
+ if (((thePattern->pnType == MF_WILDCARD_NODE) ||
709
+ (thePattern->pnType == MF_VARIABLE_NODE)) &&
710
+ (thePattern->right == NULL) && (tempPattern != NULL))
711
+ { endSlot = true; }
712
+ else
713
+ { endSlot = false; }
714
+
715
+ /*========================================*/
716
+ /* Is there a node in the pattern network */
717
+ /* that can be reused (shared)? */
718
+ /*========================================*/
719
+
720
+ newNode = FindObjectPatternNode(currentLevel,thePattern,&nodeSlotGroup,endSlot,false);
721
+
722
+ /*================================================*/
723
+ /* If the pattern node cannot be shared, then add */
724
+ /* a new pattern node to the pattern network. */
725
+ /*================================================*/
726
+
727
+ if (newNode == NULL)
728
+ { newNode = CreateNewObjectPatternNode(theEnv,thePattern,nodeSlotGroup,lastLevel,endSlot,false); }
729
+
730
+ if (thePattern->constantSelector != NULL)
731
+ {
732
+ currentLevel = newNode->nextLevel;
733
+ lastLevel = newNode;
734
+ newNode = FindObjectPatternNode(currentLevel,thePattern,&nodeSlotGroup,endSlot,true);
735
+
736
+ if (newNode == NULL)
737
+ { newNode = CreateNewObjectPatternNode(theEnv,thePattern,nodeSlotGroup,lastLevel,endSlot,true); }
738
+ }
739
+
740
+ /*=======================================================*/
741
+ /* Move on to the next field in the pattern to be added. */
742
+ /*=======================================================*/
743
+
744
+ if ((thePattern->right == NULL) && (tempPattern != NULL))
745
+ {
746
+ thePattern = tempPattern;
747
+ tempPattern = NULL;
748
+ }
749
+
750
+ lastLevel = newNode;
751
+ currentLevel = newNode->nextLevel;
752
+ thePattern = thePattern->right;
753
+ }
754
+ while ((thePattern != NULL) ? (thePattern->userData == NULL) : false);
755
+
756
+ /*==================================================*/
757
+ /* Return the leaf node of the newly added pattern. */
758
+ /*==================================================*/
759
+
760
+ newAlphaNode = lastLevel->alphaNode;
761
+ while (newAlphaNode != NULL)
762
+ {
763
+ if ((newClassBitMap == newAlphaNode->classbmp) &&
764
+ (newSlotBitMap == newAlphaNode->slotbmp) &&
765
+ IdenticalExpression(newAlphaNode->header.rightHash,rightHash))
766
+ return((struct patternNodeHeader *) newAlphaNode);
767
+ newAlphaNode = newAlphaNode->nxtInGroup;
768
+ }
769
+
770
+ newAlphaNode = get_struct(theEnv,objectAlphaNode);
771
+ InitializePatternHeader(theEnv,&newAlphaNode->header);
772
+ newAlphaNode->header.rightHash = AddHashedExpression(theEnv,rightHash);
773
+ newAlphaNode->matchTimeTag = 0L;
774
+ newAlphaNode->patternNode = lastLevel;
775
+ newAlphaNode->classbmp = newClassBitMap;
776
+ IncrementBitMapCount(newClassBitMap);
777
+ MarkBitMapClassesBusy(theEnv,newClassBitMap,1);
778
+ newAlphaNode->slotbmp = newSlotBitMap;
779
+ if (newSlotBitMap != NULL)
780
+ IncrementBitMapCount(newSlotBitMap);
781
+ newAlphaNode->bsaveID = 0L;
782
+ newAlphaNode->nxtInGroup = lastLevel->alphaNode;
783
+ lastLevel->alphaNode = newAlphaNode;
784
+ newAlphaNode->nxtTerminal = ObjectNetworkTerminalPointer(theEnv);
785
+ SetObjectNetworkTerminalPointer(theEnv,newAlphaNode);
786
+
787
+ /*
788
+ * A new terminal alpha node has just been created. For each defclass
789
+ * relevant to this alpha node, add it to that defclass'
790
+ * relevant_terminal_alpha_nodes list
791
+ */
792
+ cbmp = (const CLASS_BITMAP *) newClassBitMap->contents;
793
+ for (i = 0; i <= cbmp->maxid; i++)
794
+ {
795
+ if (TestBitMap(cbmp->map,i))
796
+ {
797
+ relevantDefclass = DefclassData(theEnv)->ClassIDMap[i];
798
+ newAlphaLink = get_struct(theEnv, classAlphaLink);
799
+ newAlphaLink->alphaNode = newAlphaNode;
800
+ newAlphaLink->next = relevantDefclass->relevant_terminal_alpha_nodes;
801
+ relevantDefclass->relevant_terminal_alpha_nodes = newAlphaLink;
802
+ }
803
+ }
804
+
805
+ return((struct patternNodeHeader *) newAlphaNode);
806
+ }
807
+
808
+ /************************************************************************
809
+ NAME : FindObjectPatternNode
810
+ DESCRIPTION : Looks for a pattern node at a specified
811
+ level in the pattern network that can be reused (shared)
812
+ with a pattern field being added to the pattern network.
813
+ INPUTS : 1) The current layer of nodes being examined in the
814
+ object pattern network
815
+ 2) The intermediate parse representation of the pattern
816
+ being added
817
+ 3) A buffer for holding the first node of a group
818
+ of slots with the same name as the new node
819
+ 4) An integer code indicating if this is the last
820
+ fiedl in a slot pattern or not
821
+ RETURNS : The old pattern network node matching the new node, or
822
+ NULL if there is none (nodeSlotGroup will hold the
823
+ place where to attach a new node)
824
+ SIDE EFFECTS : nodeSlotGroup set
825
+ NOTES : None
826
+ ************************************************************************/
827
+ static OBJECT_PATTERN_NODE *FindObjectPatternNode(
828
+ OBJECT_PATTERN_NODE *listOfNodes,
829
+ struct lhsParseNode *thePattern,
830
+ OBJECT_PATTERN_NODE **nodeSlotGroup,
831
+ bool endSlot,
832
+ bool constantSelector)
833
+ {
834
+ struct expr *compareTest;
835
+ *nodeSlotGroup = NULL;
836
+
837
+ if (constantSelector)
838
+ { compareTest = thePattern->constantValue; }
839
+ else if (thePattern->constantSelector != NULL)
840
+ { compareTest = thePattern->constantSelector; }
841
+ else
842
+ { compareTest = thePattern->networkTest; }
843
+
844
+ /*==========================================================*/
845
+ /* Loop through the nodes at the given level in the pattern */
846
+ /* network looking for a node that can be reused (shared). */
847
+ /*==========================================================*/
848
+
849
+ while (listOfNodes != NULL)
850
+ {
851
+ /*=========================================================*/
852
+ /* A object pattern node can be shared if the slot name is */
853
+ /* the same, the test is on the same field in the pattern, */
854
+ /* and the network test expressions are the same. */
855
+ /*=========================================================*/
856
+
857
+ if (((thePattern->pnType == MF_WILDCARD_NODE) || (thePattern->pnType == MF_VARIABLE_NODE)) ?
858
+ listOfNodes->multifieldNode : (listOfNodes->multifieldNode == 0))
859
+ {
860
+ if ((thePattern->slotNumber == listOfNodes->slotNameID) &&
861
+ (thePattern->index == listOfNodes->whichField) &&
862
+ (thePattern->singleFieldsAfter == listOfNodes->leaveFields) &&
863
+ (endSlot == listOfNodes->endSlot) &&
864
+ IdenticalExpression(listOfNodes->networkTest,compareTest))
865
+ return(listOfNodes);
866
+ }
867
+
868
+ /*===============================================*/
869
+ /* Find the beginning of a group of nodes with */
870
+ /* the same slot name testing on the same field. */
871
+ /*===============================================*/
872
+
873
+ if ((*nodeSlotGroup == NULL) &&
874
+ (thePattern->index == listOfNodes->whichField) &&
875
+ (thePattern->slotNumber == listOfNodes->slotNameID))
876
+ *nodeSlotGroup = listOfNodes;
877
+ listOfNodes = listOfNodes->rightNode;
878
+ }
879
+
880
+ /*==============================================*/
881
+ /* A shareable pattern node could not be found. */
882
+ /*==============================================*/
883
+
884
+ return NULL;
885
+ }
886
+
887
+ /*****************************************************************
888
+ NAME : CreateNewObjectPatternNode
889
+ DESCRIPTION : Creates a new pattern node and initializes
890
+ all of its values.
891
+ INPUTS : 1) The intermediate parse representation
892
+ of the new pattern node
893
+ 2) A pointer to the network node after
894
+ which to add the new node
895
+ 3) A pointer to the parent node on the
896
+ level above to link the new node
897
+ 4) An integer code indicating if this is the last
898
+ fiedl in a slot pattern or not
899
+ RETURNS : A pointer to the new pattern node
900
+ SIDE EFFECTS : Pattern node allocated, initialized and
901
+ attached
902
+ NOTES : None
903
+ *****************************************************************/
904
+ static OBJECT_PATTERN_NODE *CreateNewObjectPatternNode(
905
+ Environment *theEnv,
906
+ struct lhsParseNode *thePattern,
907
+ OBJECT_PATTERN_NODE *nodeSlotGroup,
908
+ OBJECT_PATTERN_NODE *upperLevel,
909
+ bool endSlot,
910
+ bool constantSelector)
911
+ {
912
+ OBJECT_PATTERN_NODE *newNode,*prvNode,*curNode;
913
+
914
+ newNode = get_struct(theEnv,objectPatternNode);
915
+ newNode->blocked = false;
916
+ newNode->multifieldNode = false;
917
+ newNode->alphaNode = NULL;
918
+ newNode->matchTimeTag = 0L;
919
+ newNode->nextLevel = NULL;
920
+ newNode->rightNode = NULL;
921
+ newNode->leftNode = NULL;
922
+ newNode->bsaveID = 0L;
923
+
924
+ if ((thePattern->constantSelector != NULL) && (! constantSelector))
925
+ { newNode->selector = true; }
926
+ else
927
+ { newNode->selector = false; }
928
+
929
+ /*===========================================================*/
930
+ /* Install the expression associated with this pattern node. */
931
+ /*===========================================================*/
932
+
933
+ if (constantSelector)
934
+ { newNode->networkTest = AddHashedExpression(theEnv,thePattern->constantValue); }
935
+ else if (thePattern->constantSelector != NULL)
936
+ { newNode->networkTest = AddHashedExpression(theEnv,thePattern->constantSelector); }
937
+ else
938
+ { newNode->networkTest = AddHashedExpression(theEnv,thePattern->networkTest); }
939
+
940
+ newNode->whichField = thePattern->index;
941
+ newNode->leaveFields = thePattern->singleFieldsAfter;
942
+
943
+ /*=========================================*/
944
+ /* Install the slot name for the new node. */
945
+ /*=========================================*/
946
+
947
+ newNode->slotNameID = thePattern->slotNumber;
948
+ if ((thePattern->pnType == MF_WILDCARD_NODE) || (thePattern->pnType == MF_VARIABLE_NODE))
949
+ newNode->multifieldNode = true;
950
+ newNode->endSlot = endSlot;
951
+
952
+ /*===============================================*/
953
+ /* Set the upper level pointer for the new node. */
954
+ /*===============================================*/
955
+
956
+ newNode->lastLevel = upperLevel;
957
+
958
+ if ((upperLevel != NULL) && (upperLevel->selector))
959
+ { AddHashedPatternNode(theEnv,upperLevel,newNode,newNode->networkTest->type,newNode->networkTest->value); }
960
+
961
+ /*==============================================*/
962
+ /* If there are no nodes with this slot name on */
963
+ /* this level, simply prepend it to the front. */
964
+ /*==============================================*/
965
+
966
+ if (nodeSlotGroup == NULL)
967
+ {
968
+ if (upperLevel == NULL)
969
+ {
970
+ newNode->rightNode = ObjectNetworkPointer(theEnv);
971
+ SetObjectNetworkPointer(theEnv,newNode);
972
+ }
973
+ else
974
+ {
975
+ newNode->rightNode = upperLevel->nextLevel;
976
+ upperLevel->nextLevel = newNode;
977
+ }
978
+ if (newNode->rightNode != NULL)
979
+ newNode->rightNode->leftNode = newNode;
980
+ return(newNode);
981
+ }
982
+
983
+ /* ===========================================================
984
+ Group this node with other nodes of the same name
985
+ testing on the same field in the pattern
986
+ on this level. This allows us to do some optimization
987
+ with constant tests on a particular slots. If we put
988
+ all constant tests for a particular slot/field group at the
989
+ end of that group, then when one of those test succeeds
990
+ during pattern-matching, we don't have to test any
991
+ more of the nodes with that slot/field name to the right.
992
+ =========================================================== */
993
+ prvNode = NULL;
994
+ curNode = nodeSlotGroup;
995
+ while ((curNode == NULL) ? false :
996
+ (curNode->slotNameID == nodeSlotGroup->slotNameID) &&
997
+ (curNode->whichField == nodeSlotGroup->whichField))
998
+ {
999
+ if ((curNode->networkTest == NULL) ? false :
1000
+ ((curNode->networkTest->type != OBJ_PN_CONSTANT) ? false :
1001
+ ((const struct ObjectCmpPNConstant *) curNode->networkTest->bitMapValue->contents)->pass))
1002
+ break;
1003
+ prvNode = curNode;
1004
+ curNode = curNode->rightNode;
1005
+ }
1006
+ if (curNode != NULL)
1007
+ {
1008
+ newNode->leftNode = curNode->leftNode;
1009
+ newNode->rightNode = curNode;
1010
+ if (curNode->leftNode != NULL)
1011
+ curNode->leftNode->rightNode = newNode;
1012
+ else if (curNode->lastLevel != NULL)
1013
+ curNode->lastLevel->nextLevel = newNode;
1014
+ else
1015
+ SetObjectNetworkPointer(theEnv,newNode);
1016
+ curNode->leftNode = newNode;
1017
+ }
1018
+ else
1019
+ {
1020
+ newNode->leftNode = prvNode;
1021
+ prvNode->rightNode = newNode;
1022
+ }
1023
+
1024
+ return(newNode);
1025
+ }
1026
+
1027
+ /********************************************************
1028
+ NAME : DetachObjectPattern
1029
+ DESCRIPTION : Removes a pattern node and all of its
1030
+ parent nodes from the pattern network. Nodes are only
1031
+ removed if they are no longer shared (i.e. a pattern
1032
+ node that has more than one child node is shared). A
1033
+ pattern from a rule is typically removed by removing
1034
+ the bottom most pattern node used by the pattern and
1035
+ then removing any parent nodes which are not shared by
1036
+ other patterns.
1037
+
1038
+ Example:
1039
+ Patterns (a b c d) and (a b e f) would be represented
1040
+ by the pattern net shown on the left. If (a b c d)
1041
+ was detached, the resultant pattern net would be the
1042
+ one shown on the right. The '=' represents an
1043
+ end-of-pattern node.
1044
+
1045
+ a a
1046
+ | |
1047
+ b b
1048
+ | |
1049
+ c--e e
1050
+ | | |
1051
+ d f f
1052
+ | | |
1053
+ = = =
1054
+ INPUTS : The pattern to be removed
1055
+ RETURNS : Nothing useful
1056
+ SIDE EFFECTS : All non-shared nodes associated with the
1057
+ pattern are removed
1058
+ NOTES : None
1059
+ ********************************************************/
1060
+ static void DetachObjectPattern(
1061
+ Environment *theEnv,
1062
+ struct patternNodeHeader *thePattern)
1063
+ {
1064
+ OBJECT_ALPHA_NODE *alphaPtr,*prv,*terminalPtr;
1065
+ OBJECT_PATTERN_NODE *patternPtr,*upperLevel;
1066
+
1067
+ /*====================================================*/
1068
+ /* Get rid of any matches stored in the alpha memory. */
1069
+ /*====================================================*/
1070
+
1071
+ alphaPtr = (OBJECT_ALPHA_NODE *) thePattern;
1072
+ ClearObjectPatternMatches(theEnv,alphaPtr);
1073
+
1074
+ /*==================================*/
1075
+ /* Remove alpha links from classes. */
1076
+ /*==================================*/
1077
+
1078
+ if (! ConstructData(theEnv)->ClearInProgress)
1079
+ {
1080
+ const CLASS_BITMAP *cbmp;
1081
+ unsigned int i;
1082
+ Defclass *relevantDefclass;
1083
+ CLASS_ALPHA_LINK *alphaLink, *lastAlpha;
1084
+
1085
+ cbmp = (const CLASS_BITMAP *) alphaPtr->classbmp->contents;
1086
+ for (i = 0; i <= cbmp->maxid; i++)
1087
+ {
1088
+ if (TestBitMap(cbmp->map,i))
1089
+ {
1090
+ relevantDefclass = DefclassData(theEnv)->ClassIDMap[i];
1091
+
1092
+ for (lastAlpha = NULL, alphaLink = relevantDefclass->relevant_terminal_alpha_nodes;
1093
+ alphaLink != NULL;
1094
+ lastAlpha = alphaLink, alphaLink = alphaLink->next)
1095
+ {
1096
+ if (alphaLink->alphaNode == alphaPtr)
1097
+ {
1098
+ if (lastAlpha == NULL)
1099
+ { relevantDefclass->relevant_terminal_alpha_nodes = alphaLink->next; }
1100
+ else
1101
+ { lastAlpha->next = alphaLink->next; }
1102
+ rtn_struct(theEnv,classAlphaLink,alphaLink);
1103
+ break;
1104
+ }
1105
+ }
1106
+ }
1107
+ }
1108
+ }
1109
+
1110
+ /*========================================================*/
1111
+ /* Unmark the classes to which the pattern is applicable */
1112
+ /* and unmark the class and slot id maps so that they can */
1113
+ /* become ephemeral. */
1114
+ /*========================================================*/
1115
+
1116
+ MarkBitMapClassesBusy(theEnv,alphaPtr->classbmp,-1);
1117
+ DeleteClassBitMap(theEnv,alphaPtr->classbmp);
1118
+ if (alphaPtr->slotbmp != NULL)
1119
+ { DecrementBitMapReferenceCount(theEnv,alphaPtr->slotbmp); }
1120
+
1121
+ /*=========================================*/
1122
+ /* Only continue deleting this pattern if */
1123
+ /* this is the last alpha memory attached. */
1124
+ /*=========================================*/
1125
+
1126
+ prv = NULL;
1127
+ terminalPtr = ObjectNetworkTerminalPointer(theEnv);
1128
+ while (terminalPtr != alphaPtr)
1129
+ {
1130
+ prv = terminalPtr;
1131
+ terminalPtr = terminalPtr->nxtTerminal;
1132
+ }
1133
+
1134
+ if (prv == NULL)
1135
+ { SetObjectNetworkTerminalPointer(theEnv,terminalPtr->nxtTerminal); }
1136
+ else
1137
+ { prv->nxtTerminal = terminalPtr->nxtTerminal; }
1138
+
1139
+ prv = NULL;
1140
+ terminalPtr = alphaPtr->patternNode->alphaNode;
1141
+ while (terminalPtr != alphaPtr)
1142
+ {
1143
+ prv = terminalPtr;
1144
+ terminalPtr = terminalPtr->nxtInGroup;
1145
+ }
1146
+
1147
+ if (prv == NULL)
1148
+ {
1149
+ if (alphaPtr->nxtInGroup != NULL)
1150
+ {
1151
+ alphaPtr->patternNode->alphaNode = alphaPtr->nxtInGroup;
1152
+ RemoveHashedExpression(theEnv,alphaPtr->header.rightHash);
1153
+ rtn_struct(theEnv,objectAlphaNode,alphaPtr);
1154
+ return;
1155
+ }
1156
+ }
1157
+ else
1158
+ {
1159
+ prv->nxtInGroup = alphaPtr->nxtInGroup;
1160
+ RemoveHashedExpression(theEnv,alphaPtr->header.rightHash);
1161
+ rtn_struct(theEnv,objectAlphaNode,alphaPtr);
1162
+ return;
1163
+ }
1164
+ alphaPtr->patternNode->alphaNode = NULL;
1165
+ RemoveHashedExpression(theEnv,alphaPtr->header.rightHash);
1166
+ upperLevel = alphaPtr->patternNode;
1167
+ rtn_struct(theEnv,objectAlphaNode,alphaPtr);
1168
+
1169
+ if (upperLevel->nextLevel != NULL)
1170
+ return;
1171
+
1172
+ /*==============================================================*/
1173
+ /* Loop until all appropriate pattern nodes have been detached. */
1174
+ /*==============================================================*/
1175
+
1176
+ while (upperLevel != NULL)
1177
+ {
1178
+ if ((upperLevel->leftNode == NULL) &&
1179
+ (upperLevel->rightNode == NULL))
1180
+ {
1181
+ /*===============================================*/
1182
+ /* Pattern node is the only node on this level. */
1183
+ /* Remove it and continue detaching other nodes */
1184
+ /* above this one, because no other patterns are */
1185
+ /* dependent upon this node. */
1186
+ /*===============================================*/
1187
+
1188
+ patternPtr = upperLevel;
1189
+ upperLevel = patternPtr->lastLevel;
1190
+
1191
+ if (upperLevel == NULL)
1192
+ SetObjectNetworkPointer(theEnv,NULL);
1193
+ else
1194
+ {
1195
+ if (upperLevel->selector)
1196
+ { RemoveHashedPatternNode(theEnv,upperLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
1197
+
1198
+ upperLevel->nextLevel = NULL;
1199
+ if (upperLevel->alphaNode != NULL)
1200
+ upperLevel = NULL;
1201
+ }
1202
+
1203
+ RemoveHashedExpression(theEnv,(Expression *) patternPtr->networkTest);
1204
+ rtn_struct(theEnv,objectPatternNode,patternPtr);
1205
+ }
1206
+ else if (upperLevel->leftNode != NULL)
1207
+ {
1208
+ /*====================================================*/
1209
+ /* Pattern node has another pattern node which must */
1210
+ /* be checked preceding it. Remove the pattern node, */
1211
+ /* but do not detach any nodes above this one. */
1212
+ /*====================================================*/
1213
+
1214
+ patternPtr = upperLevel;
1215
+
1216
+ if ((patternPtr->lastLevel != NULL) &&
1217
+ (patternPtr->lastLevel->selector))
1218
+ { RemoveHashedPatternNode(theEnv,patternPtr->lastLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
1219
+
1220
+ upperLevel->leftNode->rightNode = upperLevel->rightNode;
1221
+ if (upperLevel->rightNode != NULL)
1222
+ { upperLevel->rightNode->leftNode = upperLevel->leftNode; }
1223
+
1224
+ RemoveHashedExpression(theEnv,(Expression *) patternPtr->networkTest);
1225
+ rtn_struct(theEnv,objectPatternNode,patternPtr);
1226
+ upperLevel = NULL;
1227
+ }
1228
+ else
1229
+ {
1230
+ /*====================================================*/
1231
+ /* Pattern node has no pattern node preceding it, but */
1232
+ /* does have one succeeding it. Remove the pattern */
1233
+ /* node, but do not detach any nodes above this one. */
1234
+ /*====================================================*/
1235
+
1236
+ patternPtr = upperLevel;
1237
+ upperLevel = upperLevel->lastLevel;
1238
+ if (upperLevel == NULL)
1239
+ { SetObjectNetworkPointer(theEnv,patternPtr->rightNode); }
1240
+ else
1241
+ {
1242
+ if (upperLevel->selector)
1243
+ { RemoveHashedPatternNode(theEnv,upperLevel,patternPtr,patternPtr->networkTest->type,patternPtr->networkTest->value); }
1244
+
1245
+ upperLevel->nextLevel = patternPtr->rightNode;
1246
+ }
1247
+ patternPtr->rightNode->leftNode = NULL;
1248
+
1249
+ RemoveHashedExpression(theEnv,(Expression *) patternPtr->networkTest);
1250
+ rtn_struct(theEnv,objectPatternNode,patternPtr);
1251
+ upperLevel = NULL;
1252
+ }
1253
+ }
1254
+ }
1255
+
1256
+ /***************************************************
1257
+ NAME : ClearObjectPatternMatches
1258
+ DESCRIPTION : Removes a pattern node alpha memory
1259
+ from the list of partial matches
1260
+ on all instances (active or
1261
+ garbage collected)
1262
+ INPUTS : The pattern node to remove
1263
+ RETURNS : Nothing useful
1264
+ SIDE EFFECTS : Pattern alpha memory removed
1265
+ from all object partial match lists
1266
+ NOTES : Used when a pattern is removed
1267
+ ***************************************************/
1268
+ static void ClearObjectPatternMatches(
1269
+ Environment *theEnv,
1270
+ OBJECT_ALPHA_NODE *alphaPtr)
1271
+ {
1272
+ Instance *ins;
1273
+ IGARBAGE *igrb;
1274
+
1275
+ /* =============================================
1276
+ Loop through every active and queued instance
1277
+ ============================================= */
1278
+ ins = InstanceData(theEnv)->InstanceList;
1279
+ while (ins != NULL)
1280
+ {
1281
+ RemoveObjectPartialMatches(theEnv,ins,(struct patternNodeHeader *) alphaPtr);
1282
+ ins = ins->nxtList;
1283
+ }
1284
+
1285
+ /* ============================
1286
+ Check for garbaged instances
1287
+ ============================ */
1288
+ igrb = InstanceData(theEnv)->InstanceGarbageList;
1289
+ while (igrb != NULL)
1290
+ {
1291
+ RemoveObjectPartialMatches(theEnv,igrb->ins,(struct patternNodeHeader *) alphaPtr);
1292
+ igrb = igrb->nxt;
1293
+ }
1294
+ }
1295
+
1296
+ /***************************************************
1297
+ NAME : RemoveObjectPartialMatches
1298
+ DESCRIPTION : Removes a partial match from a
1299
+ list of partial matches for
1300
+ an instance
1301
+ INPUTS : 1) The instance
1302
+ 2) The pattern node header
1303
+ corresponding to the match
1304
+ RETURNS : Nothing useful
1305
+ SIDE EFFECTS : Match removed
1306
+ NOTES : None
1307
+ ***************************************************/
1308
+ static void RemoveObjectPartialMatches(
1309
+ Environment *theEnv,
1310
+ Instance *ins,
1311
+ struct patternNodeHeader *phead)
1312
+ {
1313
+ struct patternMatch *match_before, *match_ptr;
1314
+
1315
+ match_before = NULL;
1316
+ match_ptr = (struct patternMatch *) ins->partialMatchList;
1317
+
1318
+ /* =======================================
1319
+ Loop through every match for the object
1320
+ ======================================= */
1321
+ while (match_ptr != NULL)
1322
+ {
1323
+ if (match_ptr->matchingPattern == phead)
1324
+ {
1325
+ ins->busy--;
1326
+ if (match_before == NULL)
1327
+ {
1328
+ ins->partialMatchList = (void *) match_ptr->next;
1329
+ rtn_struct(theEnv,patternMatch,match_ptr);
1330
+ match_ptr = (struct patternMatch *) ins->partialMatchList;
1331
+ }
1332
+ else
1333
+ {
1334
+ match_before->next = match_ptr->next;
1335
+ rtn_struct(theEnv,patternMatch,match_ptr);
1336
+ match_ptr = match_before->next;
1337
+ }
1338
+ }
1339
+ else
1340
+ {
1341
+ match_before = match_ptr;
1342
+ match_ptr = match_ptr->next;
1343
+ }
1344
+ }
1345
+ }
1346
+
1347
+ /******************************************************
1348
+ NAME : CheckDuplicateSlots
1349
+ DESCRIPTION : Determines if a restriction has
1350
+ already been defined in a pattern
1351
+ INPUTS : The list of already built restrictions
1352
+ RETURNS : True if a definition already
1353
+ exists, false otherwise
1354
+ SIDE EFFECTS : An error message is printed if a
1355
+ duplicate is found
1356
+ NOTES : None
1357
+ ******************************************************/
1358
+ static bool CheckDuplicateSlots(
1359
+ Environment *theEnv,
1360
+ struct lhsParseNode *nodeList,
1361
+ CLIPSLexeme *slotName)
1362
+ {
1363
+ while (nodeList != NULL)
1364
+ {
1365
+ if (nodeList->slot == slotName)
1366
+ {
1367
+ PrintErrorID(theEnv,"OBJRTBLD",4,true);
1368
+ WriteString(theEnv,STDERR,"Multiple restrictions on attribute '");
1369
+ WriteString(theEnv,STDERR,slotName->contents);
1370
+ WriteString(theEnv,STDERR,"' not allowed.\n");
1371
+ return true;
1372
+ }
1373
+ nodeList = nodeList->right;
1374
+ }
1375
+ return false;
1376
+ }
1377
+
1378
+ /**********************************************************
1379
+ NAME : ParseClassRestriction
1380
+ DESCRIPTION : Parses the single-field constraint
1381
+ on the class an object pattern
1382
+ INPUTS : 1) The logical input source
1383
+ 2) A buffer for tokens
1384
+ RETURNS : The intermediate pattern nodes
1385
+ representing the class constraint
1386
+ (NULL on errors)
1387
+ SIDE EFFECTS : Intermediate pattern nodes allocated
1388
+ NOTES : None
1389
+ **********************************************************/
1390
+ static struct lhsParseNode *ParseClassRestriction(
1391
+ Environment *theEnv,
1392
+ const char *readSource,
1393
+ struct token *theToken)
1394
+ {
1395
+ struct lhsParseNode *tmpNode;
1396
+ CLIPSLexeme *rln;
1397
+ CONSTRAINT_RECORD *rv;
1398
+
1399
+ rv = GetConstraintRecord(theEnv);
1400
+ rv->anyAllowed = 0;
1401
+ rv->symbolsAllowed = 1;
1402
+ rln = theToken->lexemeValue;
1403
+ SavePPBuffer(theEnv," ");
1404
+ GetToken(theEnv,readSource,theToken);
1405
+ tmpNode = RestrictionParse(theEnv,readSource,theToken,false,rln,ISA_ID,rv,0);
1406
+ if (tmpNode == NULL)
1407
+ {
1408
+ RemoveConstraint(theEnv,rv);
1409
+ return NULL;
1410
+ }
1411
+ if ((theToken->tknType != RIGHT_PARENTHESIS_TOKEN) ||
1412
+ (tmpNode->pnType == MF_WILDCARD_NODE) ||
1413
+ (tmpNode->pnType == MF_VARIABLE_NODE))
1414
+ {
1415
+ PPBackup(theEnv);
1416
+ if (theToken->tknType != RIGHT_PARENTHESIS_TOKEN)
1417
+ {
1418
+ SavePPBuffer(theEnv," ");
1419
+ SavePPBuffer(theEnv,theToken->printForm);
1420
+ }
1421
+ SyntaxErrorMessage(theEnv,"class restriction in object pattern");
1422
+ ReturnLHSParseNodes(theEnv,tmpNode);
1423
+ RemoveConstraint(theEnv,rv);
1424
+ return NULL;
1425
+ }
1426
+ tmpNode->derivedConstraints = 1;
1427
+ return(tmpNode);
1428
+ }
1429
+
1430
+ /**********************************************************
1431
+ NAME : ParseNameRestriction
1432
+ DESCRIPTION : Parses the single-field constraint
1433
+ on the name of an object pattern
1434
+ INPUTS : 1) The logical input source
1435
+ 2) A buffer for tokens
1436
+ RETURNS : The intermediate pattern nodes
1437
+ representing the name constraint
1438
+ (NULL on errors)
1439
+ SIDE EFFECTS : Intermediate pattern nodes allocated
1440
+ NOTES : None
1441
+ **********************************************************/
1442
+ static struct lhsParseNode *ParseNameRestriction(
1443
+ Environment *theEnv,
1444
+ const char *readSource,
1445
+ struct token *theToken)
1446
+ {
1447
+ struct lhsParseNode *tmpNode;
1448
+ CLIPSLexeme *rln;
1449
+ CONSTRAINT_RECORD *rv;
1450
+
1451
+ rv = GetConstraintRecord(theEnv);
1452
+ rv->anyAllowed = 0;
1453
+ rv->instanceNamesAllowed = 1;
1454
+ rln = theToken->lexemeValue;
1455
+ SavePPBuffer(theEnv," ");
1456
+ GetToken(theEnv,readSource,theToken);
1457
+ tmpNode = RestrictionParse(theEnv,readSource,theToken,false,rln,NAME_ID,rv,0);
1458
+ if (tmpNode == NULL)
1459
+ {
1460
+ RemoveConstraint(theEnv,rv);
1461
+ return NULL;
1462
+ }
1463
+ if ((theToken->tknType != RIGHT_PARENTHESIS_TOKEN) ||
1464
+ (tmpNode->pnType == MF_WILDCARD_NODE) ||
1465
+ (tmpNode->pnType == MF_VARIABLE_NODE))
1466
+ {
1467
+ PPBackup(theEnv);
1468
+ if (theToken->tknType != RIGHT_PARENTHESIS_TOKEN)
1469
+ {
1470
+ SavePPBuffer(theEnv," ");
1471
+ SavePPBuffer(theEnv,theToken->printForm);
1472
+ }
1473
+ SyntaxErrorMessage(theEnv,"name restriction in object pattern");
1474
+ ReturnLHSParseNodes(theEnv,tmpNode);
1475
+ RemoveConstraint(theEnv,rv);
1476
+ return NULL;
1477
+ }
1478
+
1479
+ tmpNode->derivedConstraints = 1;
1480
+ return(tmpNode);
1481
+ }
1482
+
1483
+ /***************************************************
1484
+ NAME : ParseSlotRestriction
1485
+ DESCRIPTION : Parses the field constraint(s)
1486
+ on a slot of an object pattern
1487
+ INPUTS : 1) The logical input source
1488
+ 2) A buffer for tokens
1489
+ 3) Constraint record holding the
1490
+ unioned constraints of all the
1491
+ slots which could match the
1492
+ slot pattern
1493
+ 4) A flag indicating if any
1494
+ multifield slots match the name
1495
+ RETURNS : The intermediate pattern nodes
1496
+ representing the slot constraint(s)
1497
+ (NULL on errors)
1498
+ SIDE EFFECTS : Intermediate pattern nodes
1499
+ allocated
1500
+ NOTES : None
1501
+ ***************************************************/
1502
+ static struct lhsParseNode *ParseSlotRestriction(
1503
+ Environment *theEnv,
1504
+ const char *readSource,
1505
+ struct token *theToken,
1506
+ CONSTRAINT_RECORD *slotConstraints,
1507
+ bool multip)
1508
+ {
1509
+ struct lhsParseNode *tmpNode;
1510
+ CLIPSLexeme *slotName;
1511
+
1512
+ slotName = theToken->lexemeValue;
1513
+ SavePPBuffer(theEnv," ");
1514
+ GetToken(theEnv,readSource,theToken);
1515
+ tmpNode = RestrictionParse(theEnv,readSource,theToken,multip,slotName,FindSlotNameID(theEnv,slotName),
1516
+ slotConstraints,1);
1517
+ if (tmpNode == NULL)
1518
+ {
1519
+ RemoveConstraint(theEnv,slotConstraints);
1520
+ return NULL;
1521
+ }
1522
+ if (theToken->tknType != RIGHT_PARENTHESIS_TOKEN)
1523
+ {
1524
+ PPBackup(theEnv);
1525
+ SavePPBuffer(theEnv," ");
1526
+ SavePPBuffer(theEnv,theToken->printForm);
1527
+ SyntaxErrorMessage(theEnv,"object slot pattern");
1528
+ ReturnLHSParseNodes(theEnv,tmpNode);
1529
+ RemoveConstraint(theEnv,slotConstraints);
1530
+ return NULL;
1531
+ }
1532
+ if ((tmpNode->bottom == NULL) && (tmpNode->multifieldSlot))
1533
+ {
1534
+ PPBackup(theEnv);
1535
+ PPBackup(theEnv);
1536
+ SavePPBuffer(theEnv,")");
1537
+ }
1538
+ tmpNode->derivedConstraints = 1;
1539
+ return(tmpNode);
1540
+ }
1541
+
1542
+ /********************************************************
1543
+ NAME : NewClassBitMap
1544
+ DESCRIPTION : Creates a new bitmap large enough
1545
+ to hold all ids of classes in the
1546
+ system and initializes all the bits
1547
+ to zero or one.
1548
+ INPUTS : 1) The maximum id that will be set
1549
+ in the bitmap
1550
+ 2) An integer code indicating if all
1551
+ the bits are to be set to zero or one
1552
+ RETURNS : The new bitmap
1553
+ SIDE EFFECTS : BitMap allocated and initialized
1554
+ NOTES : None
1555
+ ********************************************************/
1556
+ static CLASS_BITMAP *NewClassBitMap(
1557
+ Environment *theEnv,
1558
+ unsigned short maxid,
1559
+ bool set)
1560
+ {
1561
+ CLASS_BITMAP *bmp;
1562
+ size_t size;
1563
+
1564
+ size = sizeof(CLASS_BITMAP) + (sizeof(char) * (maxid / BITS_PER_BYTE));
1565
+ bmp = (CLASS_BITMAP *) gm2(theEnv,size);
1566
+ ClearBitString(bmp,size);
1567
+ bmp->maxid = (unsigned short) maxid;
1568
+ InitializeClassBitMap(theEnv,bmp,set);
1569
+
1570
+ return bmp;
1571
+ }
1572
+
1573
+ /***********************************************************
1574
+ NAME : InitializeClassBitMap
1575
+ DESCRIPTION : Initializes a bitmap to all zeroes or ones.
1576
+ INPUTS : 1) The bitmap
1577
+ 2) An integer code indicating if all
1578
+ the bits are to be set to zero or one
1579
+ RETURNS : Nothing useful
1580
+ SIDE EFFECTS : The bitmap is initialized
1581
+ NOTES : None
1582
+ ***********************************************************/
1583
+ static void InitializeClassBitMap(
1584
+ Environment *theEnv,
1585
+ CLASS_BITMAP *bmp,
1586
+ bool set)
1587
+ {
1588
+ unsigned short i, bytes;
1589
+ Defclass *cls;
1590
+ Defmodule *currentModule;
1591
+
1592
+ bytes = bmp->maxid / BITS_PER_BYTE + 1;
1593
+ while (bytes > 0)
1594
+ {
1595
+ bmp->map[bytes - 1] = (char) 0;
1596
+ bytes--;
1597
+ }
1598
+
1599
+ if (set)
1600
+ {
1601
+ currentModule = GetCurrentModule(theEnv);
1602
+ for (i = 0 ; i <= bmp->maxid ; i++)
1603
+ {
1604
+ cls = DefclassData(theEnv)->ClassIDMap[i];
1605
+ if ((cls != NULL) ? DefclassInScope(theEnv,cls,currentModule) : false)
1606
+ {
1607
+ if (cls->reactive && (cls->abstract == 0))
1608
+ SetBitMap(bmp->map,i);
1609
+ }
1610
+ }
1611
+ }
1612
+ }
1613
+
1614
+ /********************************************
1615
+ NAME : DeleteIntermediateClassBitMap
1616
+ DESCRIPTION : Deallocates a bitmap
1617
+ INPUTS : The class set
1618
+ RETURNS : Nothing useful
1619
+ SIDE EFFECTS : Class set deallocated
1620
+ NOTES : None
1621
+ ********************************************/
1622
+ static void DeleteIntermediateClassBitMap(
1623
+ Environment *theEnv,
1624
+ const CLASS_BITMAP *bmp)
1625
+ {
1626
+ rm(theEnv,(void *) bmp,ClassBitMapSize(bmp));
1627
+ }
1628
+
1629
+ /******************************************************
1630
+ NAME : CopyClassBitMap
1631
+ DESCRIPTION : Increments the in use count of a
1632
+ bitmap and returns the same pointer
1633
+ INPUTS : The bitmap
1634
+ RETURNS : The bitmap
1635
+ SIDE EFFECTS : Increments the in use count
1636
+ NOTES : Class sets are shared by multiple
1637
+ copies of an object pattern within an
1638
+ OR CE. The use count prevents having
1639
+ to make duplicate copies of the bitmap
1640
+ ******************************************************/
1641
+ static void *CopyClassBitMap(
1642
+ Environment *theEnv,
1643
+ void *gset)
1644
+ {
1645
+ #if MAC_XCD
1646
+ #pragma unused(theEnv)
1647
+ #endif
1648
+
1649
+ if (gset != NULL)
1650
+ IncrementBitMapCount(gset);
1651
+ return(gset);
1652
+ }
1653
+
1654
+ /**********************************************************
1655
+ NAME : DeleteClassBitMap
1656
+ DESCRIPTION : Deallocates a bitmap,
1657
+ and decrements the busy flags of the
1658
+ classes marked in the bitmap
1659
+ INPUTS : The bitmap
1660
+ RETURNS : Nothing useful
1661
+ SIDE EFFECTS : Class set deallocated and classes unmarked
1662
+ NOTES : None
1663
+ **********************************************************/
1664
+ static void DeleteClassBitMap(
1665
+ Environment *theEnv,
1666
+ void *gset)
1667
+ {
1668
+ if (gset == NULL)
1669
+ return;
1670
+ DecrementBitMapReferenceCount(theEnv,(CLIPSBitMap *) gset);
1671
+ }
1672
+
1673
+ /***************************************************
1674
+ NAME : MarkBitMapClassesBusy
1675
+ DESCRIPTION : Increments/Decrements busy counts
1676
+ of all classes marked in a bitmap
1677
+ INPUTS : 1) The bitmap hash node
1678
+ 2) 1 or -1 (to increment or
1679
+ decrement class busy counts)
1680
+ RETURNS : Nothing useful
1681
+ SIDE EFFECTS : Bitmap class busy counts updated
1682
+ NOTES : None
1683
+ ***************************************************/
1684
+ static void MarkBitMapClassesBusy(
1685
+ Environment *theEnv,
1686
+ CLIPSBitMap *bmphn,
1687
+ int offset)
1688
+ {
1689
+ const CLASS_BITMAP *bmp;
1690
+ unsigned short i;
1691
+ Defclass *cls;
1692
+
1693
+ /* ====================================
1694
+ If a clear is in progress, we do not
1695
+ have to worry about busy counts
1696
+ ==================================== */
1697
+ if (ConstructData(theEnv)->ClearInProgress)
1698
+ return;
1699
+ bmp = (const CLASS_BITMAP *) bmphn->contents;
1700
+ for (i = 0 ; i <= bmp->maxid ; i++)
1701
+ if (TestBitMap(bmp->map,i))
1702
+ {
1703
+ cls = DefclassData(theEnv)->ClassIDMap[i];
1704
+ cls->busy += (unsigned int) offset;
1705
+ }
1706
+ }
1707
+
1708
+ /****************************************************
1709
+ NAME : EmptyClassBitMap
1710
+ DESCRIPTION : Determines if one or more bits
1711
+ are marked in a bitmap
1712
+ INPUTS : The bitmap
1713
+ RETURNS : True if the set has no bits
1714
+ marked, false otherwise
1715
+ SIDE EFFECTS : None
1716
+ NOTES : None
1717
+ ****************************************************/
1718
+ static bool EmptyClassBitMap(
1719
+ CLASS_BITMAP *bmp)
1720
+ {
1721
+ unsigned short bytes;
1722
+
1723
+ bytes = (unsigned short) (bmp->maxid / BITS_PER_BYTE + 1);
1724
+ while (bytes > 0)
1725
+ {
1726
+ if (bmp->map[bytes - 1] != (char) 0)
1727
+ return false;
1728
+ bytes--;
1729
+ }
1730
+ return true;
1731
+ }
1732
+
1733
+ /***************************************************
1734
+ NAME : IdenticalClassBitMap
1735
+ DESCRIPTION : Determines if two bitmaps
1736
+ are identical
1737
+ INPUTS : 1) First bitmap
1738
+ 2) Second bitmap
1739
+ RETURNS : True if bitmaps are the same,
1740
+ false otherwise
1741
+ SIDE EFFECTS : None
1742
+ NOTES : None
1743
+ ***************************************************/
1744
+ static bool IdenticalClassBitMap(
1745
+ const CLASS_BITMAP *cs1,
1746
+ const CLASS_BITMAP *cs2)
1747
+ {
1748
+ unsigned short i;
1749
+
1750
+ if (cs1->maxid != cs2->maxid)
1751
+ return false;
1752
+ for (i = 0 ; i < (cs1->maxid / BITS_PER_BYTE + 1) ; i++)
1753
+ if (cs1->map[i] != cs2->map[i])
1754
+ return false;
1755
+ return true;
1756
+ }
1757
+
1758
+ /*****************************************************************
1759
+ NAME : ProcessClassRestriction
1760
+ DESCRIPTION : Examines a class restriction and forms a bitmap
1761
+ corresponding to the maximal set of classes which
1762
+ can satisfy a static analysis of the restriction
1763
+ INPUTS : 1) The bitmap to mark classes in
1764
+ 2) The lhsParseNodes of the restriction
1765
+ 3) A flag indicating if this is the first
1766
+ non-recursive call or not
1767
+ RETURNS : True if all OK, false otherwise
1768
+ SIDE EFFECTS : Class bitmap set and lhsParseNodes corressponding
1769
+ to constant restrictions are removed
1770
+ NOTES : None
1771
+ *****************************************************************/
1772
+ static bool ProcessClassRestriction(
1773
+ Environment *theEnv,
1774
+ CLASS_BITMAP *clsset,
1775
+ struct lhsParseNode **classRestrictions,
1776
+ bool recursiveCall)
1777
+ {
1778
+ struct lhsParseNode *chk,**oraddr;
1779
+ CLASS_BITMAP *tmpset1,*tmpset2;
1780
+ bool constant_restriction = true;
1781
+
1782
+ if (*classRestrictions == NULL)
1783
+ {
1784
+ if (recursiveCall)
1785
+ InitializeClassBitMap(theEnv,clsset,true);
1786
+ return true;
1787
+ }
1788
+
1789
+ /* ===============================================
1790
+ Determine the corresponding class set and union
1791
+ it with the current total class set. If an AND
1792
+ restriction is comprised entirely of symbols,
1793
+ it can be removed
1794
+ =============================================== */
1795
+ tmpset1 = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,1);
1796
+ tmpset2 = NewClassBitMap(theEnv,DefclassData(theEnv)->MaxClassID - 1,0);
1797
+ for (chk = *classRestrictions ; chk != NULL ; chk = chk->right)
1798
+ {
1799
+ if (chk->pnType == SYMBOL_NODE)
1800
+ {
1801
+ const char *className = chk->lexemeValue->contents;
1802
+
1803
+ chk->value = LookupDefclassByMdlOrScope(theEnv,className);
1804
+ if (chk->value == NULL)
1805
+ {
1806
+ PrintErrorID(theEnv,"OBJRTBLD",5,false);
1807
+ WriteString(theEnv,STDERR,"Undefined class '");
1808
+ WriteString(theEnv,STDERR,className);
1809
+ WriteString(theEnv,STDERR,"' in object pattern.\n");
1810
+ DeleteIntermediateClassBitMap(theEnv,tmpset1);
1811
+ DeleteIntermediateClassBitMap(theEnv,tmpset2);
1812
+ return false;
1813
+ }
1814
+ if (chk->negated)
1815
+ {
1816
+ InitializeClassBitMap(theEnv,tmpset2,true);
1817
+ MarkBitMapSubclasses(tmpset2->map,(Defclass *) chk->value,0);
1818
+ }
1819
+ else
1820
+ {
1821
+ InitializeClassBitMap(theEnv,tmpset2,false);
1822
+ MarkBitMapSubclasses(tmpset2->map,(Defclass *) chk->value,1);
1823
+ }
1824
+ IntersectClassBitMaps(tmpset1,tmpset2);
1825
+ }
1826
+ else
1827
+ constant_restriction = false;
1828
+ }
1829
+ if (EmptyClassBitMap(tmpset1))
1830
+ {
1831
+ PrintErrorID(theEnv,"OBJRTBLD",2,false);
1832
+ WriteString(theEnv,STDERR,"No objects of existing classes can satisfy ");
1833
+ WriteString(theEnv,STDERR,"'is-a' restriction in object pattern.\n");
1834
+ DeleteIntermediateClassBitMap(theEnv,tmpset1);
1835
+ DeleteIntermediateClassBitMap(theEnv,tmpset2);
1836
+ return false;
1837
+ }
1838
+ if (constant_restriction)
1839
+ {
1840
+ chk = *classRestrictions;
1841
+ *classRestrictions = chk->bottom;
1842
+ chk->bottom = NULL;
1843
+ ReturnLHSParseNodes(theEnv,chk);
1844
+ oraddr = classRestrictions;
1845
+ }
1846
+ else
1847
+ oraddr = &(*classRestrictions)->bottom;
1848
+ UnionClassBitMaps(clsset,tmpset1);
1849
+ DeleteIntermediateClassBitMap(theEnv,tmpset1);
1850
+ DeleteIntermediateClassBitMap(theEnv,tmpset2);
1851
+
1852
+ /* =====================================
1853
+ Process the next OR class restriction
1854
+ ===================================== */
1855
+ return(ProcessClassRestriction(theEnv,clsset,oraddr,false));
1856
+ }
1857
+
1858
+ /****************************************************************
1859
+ NAME : ProcessSlotRestriction
1860
+ DESCRIPTION : Determines which slots could match the slot
1861
+ pattern and determines the union of all
1862
+ constraints for the pattern
1863
+ INPUTS : 1) The class set
1864
+ 2) The slot name
1865
+ 3) A buffer to hold a flag indicating if
1866
+ any multifield slots are found w/ this name
1867
+ RETURNS : A union of the constraints on all the slots
1868
+ which could match the slots (NULL if no
1869
+ slots found)
1870
+ SIDE EFFECTS : The class bitmap set is marked/cleared
1871
+ NOTES : None
1872
+ ****************************************************************/
1873
+ static CONSTRAINT_RECORD *ProcessSlotRestriction(
1874
+ Environment *theEnv,
1875
+ CLASS_BITMAP *clsset,
1876
+ CLIPSLexeme *slotName,
1877
+ bool *multip)
1878
+ {
1879
+ Defclass *cls;
1880
+ int si;
1881
+ CONSTRAINT_RECORD *totalConstraints = NULL,*tmpConstraints;
1882
+ unsigned i;
1883
+
1884
+ *multip = false;
1885
+ for (i = 0 ; i < CLASS_TABLE_HASH_SIZE ; i++)
1886
+ for (cls = DefclassData(theEnv)->ClassTable[i] ; cls != NULL ; cls = cls->nxtHash)
1887
+ {
1888
+ if (TestBitMap(clsset->map,cls->id))
1889
+ {
1890
+ si = FindInstanceTemplateSlot(theEnv,cls,slotName);
1891
+ if ((si != -1) ? cls->instanceTemplate[si]->reactive : false)
1892
+ {
1893
+ if (cls->instanceTemplate[si]->multiple)
1894
+ *multip = true;
1895
+ tmpConstraints =
1896
+ UnionConstraints(theEnv,cls->instanceTemplate[si]->constraint,totalConstraints);
1897
+ RemoveConstraint(theEnv,totalConstraints);
1898
+ totalConstraints = tmpConstraints;
1899
+ }
1900
+ else
1901
+ ClearBitMap(clsset->map,cls->id);
1902
+ }
1903
+ }
1904
+ return(totalConstraints);
1905
+ }
1906
+
1907
+ /****************************************************
1908
+ NAME : IntersectClassBitMaps
1909
+ DESCRIPTION : Bitwise-ands two bitmaps and stores
1910
+ the result in the first
1911
+ INPUTS : The two bitmaps
1912
+ RETURNS : Nothing useful
1913
+ SIDE EFFECTS : ClassBitMaps anded
1914
+ NOTES : Assumes the first bitmap is at least
1915
+ as large as the second
1916
+ ****************************************************/
1917
+ static void IntersectClassBitMaps(
1918
+ CLASS_BITMAP *cs1,
1919
+ CLASS_BITMAP *cs2)
1920
+ {
1921
+ unsigned short bytes;
1922
+
1923
+ bytes = (unsigned short) (cs2->maxid / BITS_PER_BYTE + 1);
1924
+ while (bytes > 0)
1925
+ {
1926
+ cs1->map[bytes - 1] &= cs2->map[bytes - 1];
1927
+ bytes--;
1928
+ }
1929
+ }
1930
+
1931
+ /****************************************************
1932
+ NAME : UnionClassBitMaps
1933
+ DESCRIPTION : Bitwise-ors two bitmaps and stores
1934
+ the result in the first
1935
+ INPUTS : The two bitmaps
1936
+ RETURNS : Nothing useful
1937
+ SIDE EFFECTS : ClassBitMaps ored
1938
+ NOTES : Assumes the first bitmap is at least
1939
+ as large as the second
1940
+ ****************************************************/
1941
+ static void UnionClassBitMaps(
1942
+ CLASS_BITMAP *cs1,
1943
+ CLASS_BITMAP *cs2)
1944
+ {
1945
+ unsigned short bytes;
1946
+
1947
+ bytes = (unsigned short) (cs2->maxid / BITS_PER_BYTE + 1);
1948
+ while (bytes > 0)
1949
+ {
1950
+ cs1->map[bytes - 1] |= cs2->map[bytes - 1];
1951
+ bytes--;
1952
+ }
1953
+ }
1954
+
1955
+ /*****************************************************
1956
+ NAME : PackClassBitMap
1957
+ DESCRIPTION : This routine packs a bitmap
1958
+ bitmap such that at least one of
1959
+ the bits in the rightmost byte is
1960
+ set (i.e. the bitmap takes up
1961
+ the smallest space possible).
1962
+ INPUTS : The bitmap
1963
+ RETURNS : The new (packed) bitmap
1964
+ SIDE EFFECTS : The oldset is deallocated
1965
+ NOTES : None
1966
+ *****************************************************/
1967
+ static CLASS_BITMAP *PackClassBitMap(
1968
+ Environment *theEnv,
1969
+ CLASS_BITMAP *oldset)
1970
+ {
1971
+ unsigned short newmaxid;
1972
+ CLASS_BITMAP *newset;
1973
+
1974
+ for (newmaxid = oldset->maxid ; newmaxid > 0 ; newmaxid--)
1975
+ if (TestBitMap(oldset->map,newmaxid))
1976
+ break;
1977
+ if (newmaxid != oldset->maxid)
1978
+ {
1979
+ newset = NewClassBitMap(theEnv,newmaxid,0);
1980
+ GenCopyMemory(char,newmaxid / BITS_PER_BYTE + 1,newset->map,oldset->map);
1981
+ DeleteIntermediateClassBitMap(theEnv,oldset);
1982
+ }
1983
+ else
1984
+ newset = oldset;
1985
+ return(newset);
1986
+ }
1987
+
1988
+ /*****************************************************************
1989
+ NAME : FilterObjectPattern
1990
+ DESCRIPTION : Appends an extra node to hold the bitmap,
1991
+ and finds is-a and name nodes
1992
+ INPUTS : 1) The object pattern parser address
1993
+ to give to a default is-a slot
1994
+ 2) The unfiltered slot list
1995
+ 3) A buffer to hold the address of
1996
+ the class bitmap restriction node
1997
+ 4) A buffer to hold the address of
1998
+ the is-a restriction node
1999
+ 4) A buffer to hold the address of
2000
+ the name restriction node
2001
+ RETURNS : The filtered slot list
2002
+ SIDE EFFECTS : clsset is attached to extra slot pattern
2003
+ Pointers to the is-a and name slots are also
2004
+ stored (if they exist) for easy reference
2005
+ NOTES : None
2006
+ *****************************************************************/
2007
+ static struct lhsParseNode *FilterObjectPattern(
2008
+ Environment *theEnv,
2009
+ struct patternParser *selfPatternType,
2010
+ struct lhsParseNode *unfilteredSlots,
2011
+ struct lhsParseNode **bitmap_slot,
2012
+ struct lhsParseNode **isa_slot,
2013
+ struct lhsParseNode **name_slot)
2014
+ {
2015
+ struct lhsParseNode *prv,*cur;
2016
+
2017
+ *isa_slot = NULL;
2018
+ *name_slot = NULL;
2019
+
2020
+ /* ============================================
2021
+ Create a dummy node to attach to the end
2022
+ of the pattern which holds the class bitmap.
2023
+ ============================================ */
2024
+ *bitmap_slot = GetLHSParseNode(theEnv);
2025
+ (*bitmap_slot)->pnType = SF_WILDCARD_NODE;
2026
+ (*bitmap_slot)->slot = DefclassData(theEnv)->ISA_SYMBOL;
2027
+ (*bitmap_slot)->slotNumber = ISA_ID;
2028
+ (*bitmap_slot)->index = 1;
2029
+ (*bitmap_slot)->patternType = selfPatternType;
2030
+ (*bitmap_slot)->userData = unfilteredSlots->userData;
2031
+ unfilteredSlots->userData = NULL;
2032
+
2033
+ /* ========================
2034
+ Find is-a and name nodes
2035
+ ======================== */
2036
+ prv = NULL;
2037
+ cur = unfilteredSlots;
2038
+ while (cur != NULL)
2039
+ {
2040
+ if (cur->slot == DefclassData(theEnv)->ISA_SYMBOL)
2041
+ *isa_slot = cur;
2042
+ else if (cur->slot == DefclassData(theEnv)->NAME_SYMBOL)
2043
+ *name_slot = cur;
2044
+ prv = cur;
2045
+ cur = cur->right;
2046
+ }
2047
+
2048
+ /* ================================
2049
+ Add the class bitmap conditional
2050
+ element to end of pattern
2051
+ ================================ */
2052
+ if (prv == NULL)
2053
+ unfilteredSlots = *bitmap_slot;
2054
+ else
2055
+ prv->right = *bitmap_slot;
2056
+ return(unfilteredSlots);
2057
+ }
2058
+
2059
+ /***************************************************
2060
+ NAME : FormSlotBitMap
2061
+ DESCRIPTION : Examines an object pattern and
2062
+ forms a minimal bitmap marking
2063
+ the ids of the slots used in
2064
+ the pattern
2065
+ INPUTS : The intermediate parsed pattern
2066
+ RETURNS : The new slot bitmap (can be NULL)
2067
+ SIDE EFFECTS : Bitmap created and added to hash
2068
+ table - corresponding bits set
2069
+ for ids of slots used in pattern
2070
+ NOTES : None
2071
+ ***************************************************/
2072
+ static CLIPSBitMap *FormSlotBitMap(
2073
+ Environment *theEnv,
2074
+ struct lhsParseNode *thePattern)
2075
+ {
2076
+ struct lhsParseNode *node;
2077
+ unsigned short maxSlotID = USHRT_MAX;
2078
+ unsigned size;
2079
+ SLOT_BITMAP *bmp;
2080
+ CLIPSBitMap *hshBmp;
2081
+
2082
+ /*==========================================*/
2083
+ /* Find the largest slot id in the pattern. */
2084
+ /*==========================================*/
2085
+
2086
+ for (node = thePattern ; node != NULL ; node = node->right)
2087
+ {
2088
+ if (((node->slotNumber > maxSlotID) ||
2089
+ (maxSlotID == USHRT_MAX)) &&
2090
+ (node->slotNumber != UNSPECIFIED_SLOT))
2091
+ { maxSlotID = node->slotNumber; }
2092
+ }
2093
+
2094
+ /*==================================================*/
2095
+ /* If the pattern contains no slot tests or only */
2096
+ /* tests on the class or name (which do not change) */
2097
+ /* do not store a slot bitmap. */
2098
+ /*==================================================*/
2099
+
2100
+ if ((maxSlotID == ISA_ID) ||
2101
+ (maxSlotID == NAME_ID) ||
2102
+ (maxSlotID == USHRT_MAX))
2103
+ { return NULL; }
2104
+
2105
+ /*======================================*/
2106
+ /* Initialize the bitmap to all zeroes. */
2107
+ /*======================================*/
2108
+
2109
+ size = (sizeof(SLOT_BITMAP) + (sizeof(char) * (maxSlotID / BITS_PER_BYTE)));
2110
+ bmp = (SLOT_BITMAP *) gm2(theEnv,size);
2111
+ ClearBitString(bmp,size);
2112
+ bmp->maxid = (unsigned short) maxSlotID;
2113
+
2114
+ /*===============================================*/
2115
+ /* Add (retrieve) a bitmap to (from) the bitmap */
2116
+ /* hash table which has a corresponding bit set */
2117
+ /* for the id of every slot used in the pattern. */
2118
+ /*===============================================*/
2119
+
2120
+ for (node = thePattern ; node != NULL ; node = node->right)
2121
+ { SetBitMap(bmp->map,node->slotNumber); }
2122
+
2123
+ hshBmp = (CLIPSBitMap *) AddBitMap(theEnv,bmp,SlotBitMapSize(bmp));
2124
+ rm(theEnv,bmp,size);
2125
+
2126
+ return hshBmp;
2127
+ }
2128
+
2129
+ /****************************************************
2130
+ NAME : RemoveSlotExistenceTests
2131
+ DESCRIPTION : Removes slot existence test since
2132
+ these are accounted for by class
2133
+ bitmap or name slot.
2134
+ INPUTS : 1) The intermediate pattern nodes
2135
+ 2) A buffer to hold the class bitmap
2136
+ RETURNS : The filtered list
2137
+ SIDE EFFECTS : Slot existence tests removed
2138
+ NOTES : None
2139
+ ****************************************************/
2140
+ static struct lhsParseNode *RemoveSlotExistenceTests(
2141
+ Environment *theEnv,
2142
+ struct lhsParseNode *thePattern,
2143
+ CLIPSBitMap **bmp)
2144
+ {
2145
+ struct lhsParseNode *tempPattern = thePattern;
2146
+ struct lhsParseNode *lastPattern = NULL, *head = thePattern;
2147
+
2148
+ while (tempPattern != NULL)
2149
+ {
2150
+ /* ==========================================
2151
+ Remember the class bitmap for this pattern
2152
+ ========================================== */
2153
+ if (tempPattern->userData != NULL)
2154
+ {
2155
+ *bmp = (CLIPSBitMap *) tempPattern->userData;
2156
+ lastPattern = tempPattern;
2157
+ tempPattern = tempPattern->right;
2158
+ }
2159
+
2160
+ /* ===========================================================
2161
+ A single field slot that has no pattern network expression
2162
+ associated with it can be removed (i.e. any value contained
2163
+ in this slot will satisfy the pattern being matched).
2164
+ =========================================================== */
2165
+ else if (((tempPattern->pnType == SF_WILDCARD_NODE) ||
2166
+ (tempPattern->pnType == SF_VARIABLE_NODE)) &&
2167
+ (tempPattern->networkTest == NULL))
2168
+ {
2169
+ if (lastPattern != NULL) lastPattern->right = tempPattern->right;
2170
+ else head = tempPattern->right;
2171
+
2172
+ tempPattern->right = NULL;
2173
+ ReturnLHSParseNodes(theEnv,tempPattern);
2174
+
2175
+ if (lastPattern != NULL) tempPattern = lastPattern->right;
2176
+ else tempPattern = head;
2177
+ }
2178
+
2179
+ /* =====================================================
2180
+ A multifield variable or wildcard within a multifield
2181
+ slot can be removed if there are no other multifield
2182
+ variables or wildcards contained in the same slot
2183
+ (and the multifield has no expressions which must be
2184
+ evaluated in the fact pattern network).
2185
+ ===================================================== */
2186
+ else if (((tempPattern->pnType == MF_WILDCARD_NODE) || (tempPattern->pnType == MF_VARIABLE_NODE)) &&
2187
+ (tempPattern->multifieldSlot == false) &&
2188
+ (tempPattern->networkTest == NULL) &&
2189
+ (tempPattern->multiFieldsBefore == 0) &&
2190
+ (tempPattern->multiFieldsAfter == 0))
2191
+ {
2192
+ if (lastPattern != NULL) lastPattern->right = tempPattern->right;
2193
+ else head = tempPattern->right;
2194
+
2195
+ tempPattern->right = NULL;
2196
+ ReturnLHSParseNodes(theEnv,tempPattern);
2197
+
2198
+ if (lastPattern != NULL) tempPattern = lastPattern->right;
2199
+ else tempPattern = head;
2200
+ }
2201
+
2202
+ /* ================================================================
2203
+ A multifield wildcard or variable contained in a multifield slot
2204
+ that contains no other multifield wildcards or variables, but
2205
+ does have an expression that must be evaluated, can be changed
2206
+ to a single field pattern node with the same expression.
2207
+ ================================================================ */
2208
+ else if (((tempPattern->pnType == MF_WILDCARD_NODE) || (tempPattern->pnType == MF_VARIABLE_NODE)) &&
2209
+ (tempPattern->multifieldSlot == false) &&
2210
+ (tempPattern->networkTest != NULL) &&
2211
+ (tempPattern->multiFieldsBefore == 0) &&
2212
+ (tempPattern->multiFieldsAfter == 0))
2213
+ {
2214
+ tempPattern->pnType = SF_WILDCARD_NODE;
2215
+ lastPattern = tempPattern;
2216
+ tempPattern = tempPattern->right;
2217
+ }
2218
+
2219
+ /* =======================================================
2220
+ If we're dealing with a multifield slot with no slot
2221
+ restrictions, then treat the multfield slot as a single
2222
+ field slot, but attach a test which verifies that the
2223
+ slot contains a zero length multifield value.
2224
+ ======================================================= */
2225
+ else if ((tempPattern->pnType == MF_WILDCARD_NODE) &&
2226
+ (tempPattern->multifieldSlot == true) &&
2227
+ (tempPattern->bottom == NULL))
2228
+ {
2229
+ tempPattern->pnType = SF_WILDCARD_NODE;
2230
+ GenObjectZeroLengthTest(theEnv,tempPattern);
2231
+ tempPattern->multifieldSlot = false;
2232
+ lastPattern = tempPattern;
2233
+ tempPattern = tempPattern->right;
2234
+ }
2235
+
2236
+ /* ======================================================
2237
+ Recursively call RemoveSlotExistenceTests for the slot
2238
+ restrictions contained within a multifield slot.
2239
+ ====================================================== */
2240
+ else if ((tempPattern->pnType == MF_WILDCARD_NODE) &&
2241
+ (tempPattern->multifieldSlot == true))
2242
+ {
2243
+ /* =====================================================
2244
+ Add an expression to the first pattern restriction in
2245
+ the multifield slot that determines whether or not
2246
+ the fact's slot value contains the minimum number of
2247
+ required fields to satisfy the pattern restrictions
2248
+ for this slot. The length check is place before any
2249
+ other tests, so that preceeding checks do not have to
2250
+ determine if there are enough fields in the slot to
2251
+ safely retrieve a value.
2252
+ ===================================================== */
2253
+ GenObjectLengthTest(theEnv,tempPattern->bottom);
2254
+
2255
+ /* =======================================================
2256
+ Remove any unneeded pattern restrictions from the slot.
2257
+ ======================================================= */
2258
+ tempPattern->bottom = RemoveSlotExistenceTests(theEnv,tempPattern->bottom,bmp);
2259
+
2260
+ /* =========================================================
2261
+ If the slot no longer contains any restrictions, then the
2262
+ multifield slot can be completely removed. In any case,
2263
+ move on to the next slot to be examined for removal.
2264
+ ========================================================= */
2265
+ if (tempPattern->bottom == NULL)
2266
+ {
2267
+ if (lastPattern != NULL) lastPattern->right = tempPattern->right;
2268
+ else head = tempPattern->right;
2269
+
2270
+ tempPattern->right = NULL;
2271
+ ReturnLHSParseNodes(theEnv,tempPattern);
2272
+
2273
+ if (lastPattern != NULL) tempPattern = lastPattern->right;
2274
+ else tempPattern = head;
2275
+ }
2276
+ else
2277
+ {
2278
+ lastPattern = tempPattern;
2279
+ tempPattern = tempPattern->right;
2280
+ }
2281
+ }
2282
+
2283
+ /* =====================================================
2284
+ If none of the other tests for removing slots or slot
2285
+ restrictions apply, then move on to the next slot or
2286
+ slot restriction to be tested.
2287
+ ===================================================== */
2288
+ else
2289
+ {
2290
+ lastPattern = tempPattern;
2291
+ tempPattern = tempPattern->right;
2292
+ }
2293
+ }
2294
+
2295
+ /* ====================================
2296
+ Return the pattern with unused slots
2297
+ and slot restrictions removed.
2298
+ ==================================== */
2299
+ return(head);
2300
+ }
2301
+
2302
+ #endif
2303
+
2304
+ /**************************************************************
2305
+ NAME : ObjectMatchDelayParse
2306
+ DESCRIPTION : Parses the object-pattern-match-delay function
2307
+ INPUTS : 1) The function call expression
2308
+ 2) The logical name of the input source
2309
+ RETURNS : The top expression with the other
2310
+ action expressions attached
2311
+ SIDE EFFECTS : Parses the function call and attaches
2312
+ the appropriate arguments to the
2313
+ top node
2314
+ NOTES : None
2315
+ **************************************************************/
2316
+ static Expression *ObjectMatchDelayParse(
2317
+ Environment *theEnv,
2318
+ struct expr *top,
2319
+ const char *infile)
2320
+ {
2321
+ struct token tkn;
2322
+
2323
+ IncrementIndentDepth(theEnv,3);
2324
+ PPCRAndIndent(theEnv);
2325
+ top->argList = GroupActions(theEnv,infile,&tkn,true,NULL,false);
2326
+ PPBackup(theEnv);
2327
+ PPBackup(theEnv);
2328
+ SavePPBuffer(theEnv,tkn.printForm);
2329
+ DecrementIndentDepth(theEnv,3);
2330
+ if (top->argList == NULL)
2331
+ {
2332
+ ReturnExpression(theEnv,top);
2333
+ return NULL;
2334
+ }
2335
+ return(top);
2336
+ }
2337
+
2338
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
2339
+
2340
+ /***************************************************
2341
+ NAME : MarkObjectPtnIncrementalReset
2342
+ DESCRIPTION : Marks/unmarks an object pattern for
2343
+ incremental reset
2344
+ INPUTS : 1) The object pattern alpha node
2345
+ 2) The value to which to set the
2346
+ incremental reset flag
2347
+ RETURNS : Nothing useful
2348
+ SIDE EFFECTS : The pattern node is set/unset
2349
+ NOTES : The pattern node can only be
2350
+ set if it is a new node and
2351
+ thus marked for initialization
2352
+ by PlaceObjectPattern
2353
+ ***************************************************/
2354
+ static void MarkObjectPtnIncrementalReset(
2355
+ Environment *theEnv,
2356
+ struct patternNodeHeader *thePattern,
2357
+ bool value)
2358
+ {
2359
+ #if MAC_XCD
2360
+ #pragma unused(theEnv)
2361
+ #endif
2362
+
2363
+ if (thePattern->initialize == false)
2364
+ return;
2365
+ thePattern->initialize = value;
2366
+ }
2367
+
2368
+ /***********************************************************
2369
+ NAME : ObjectIncrementalReset
2370
+ DESCRIPTION : Performs an assert for all instances in the
2371
+ system. All new patterns in the pattern
2372
+ network from the new rule have been marked
2373
+ as needing processing. Old patterns will
2374
+ be ignored.
2375
+ INPUTS : None
2376
+ RETURNS : Nothing useful
2377
+ SIDE EFFECTS : All objects driven through new patterns
2378
+ NOTES : None
2379
+ ***********************************************************/
2380
+ static void ObjectIncrementalReset(
2381
+ Environment *theEnv)
2382
+ {
2383
+ Instance *ins;
2384
+
2385
+ for (ins = InstanceData(theEnv)->InstanceList ; ins != NULL ; ins = ins->nxtList)
2386
+ ObjectNetworkAction(theEnv,OBJECT_ASSERT,ins,-1);
2387
+ }
2388
+
2389
+ #endif
2390
+
2391
+ #endif
2392
+
2393
+