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,1524 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.41 07/12/21 */
5
+ /* */
6
+ /* OBJECT PATTERN MATCHER MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: RETE Network Interface for Objects */
11
+ /* */
12
+ /* Principal Programmer(s): */
13
+ /* Brian L. Dantes */
14
+ /* */
15
+ /* Contributing Programmer(s): */
16
+ /* */
17
+ /* Revision History: */
18
+ /* */
19
+ /* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
20
+ /* */
21
+ /* 6.24: Removed INCREMENTAL_RESET and */
22
+ /* LOGICAL_DEPENDENCIES compilation flags. */
23
+ /* */
24
+ /* Converted INSTANCE_PATTERN_MATCHING to */
25
+ /* DEFRULE_CONSTRUCT. */
26
+ /* */
27
+ /* Renamed BOOLEAN macro type to intBool. */
28
+ /* */
29
+ /* 6.30: Modified the QueueObjectMatchAction function */
30
+ /* so that instance retract actions always occur */
31
+ /* before instance assert and modify actions. */
32
+ /* This prevents the pattern matching process */
33
+ /* from attempting the evaluation of a join */
34
+ /* expression that accesses the slots of a */
35
+ /* retracted instance. */
36
+ /* */
37
+ /* Added support for hashed alpha memories. */
38
+ /* */
39
+ /* Support for long long integers. */
40
+ /* */
41
+ /* Added support for hashed comparisons to */
42
+ /* constants. */
43
+ /* */
44
+ /* 6.31: Optimization for marking relevant alpha nodes */
45
+ /* in the object pattern network. */
46
+ /* */
47
+ /* 6.32: Fixed instance redefinition crash with rules */
48
+ /* in JNSimpleCompareFunction1 when deleted */
49
+ /* instance slots are referenced. */
50
+ /* */
51
+ /* 6.40: Added Env prefix to GetEvaluationError and */
52
+ /* SetEvaluationError functions. */
53
+ /* */
54
+ /* Added Env prefix to GetHaltExecution and */
55
+ /* SetHaltExecution functions. */
56
+ /* */
57
+ /* Pragma once and other inclusion changes. */
58
+ /* */
59
+ /* Added support for booleans with <stdbool.h>. */
60
+ /* */
61
+ /* Removed use of void pointers for specific */
62
+ /* data structures. */
63
+ /* */
64
+ /* UDF redesign. */
65
+ /* */
66
+ /* 6.41: Added Env prefix to GetEvaluationError and */
67
+ /* SetEvaluationError functions. */
68
+ /* */
69
+ /*************************************************************/
70
+ /* =========================================
71
+ *****************************************
72
+ EXTERNAL DEFINITIONS
73
+ =========================================
74
+ ***************************************** */
75
+ #include "setup.h"
76
+
77
+ #if DEFRULE_CONSTRUCT && OBJECT_SYSTEM
78
+
79
+ #include "classfun.h"
80
+ #include "memalloc.h"
81
+ #include "drive.h"
82
+ #include "engine.h"
83
+ #include "envrnmnt.h"
84
+ #if (! RUN_TIME) && (! BLOAD_ONLY)
85
+ #include "incrrset.h"
86
+ #endif
87
+ #include "lgcldpnd.h"
88
+ #include "multifld.h"
89
+ #include "objrtfnx.h"
90
+ #include "objrtmch.h"
91
+ #include "prntutil.h"
92
+ #include "reteutil.h"
93
+ #include "ruledlt.h"
94
+ #include "reorder.h"
95
+ #include "retract.h"
96
+ #include "router.h"
97
+
98
+ #include "insmngr.h"
99
+
100
+ /***************************************/
101
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
102
+ /***************************************/
103
+
104
+ static void QueueObjectMatchAction(Environment *,int,Instance *,int);
105
+ static SLOT_BITMAP *QueueModifySlotMap(Environment *,SLOT_BITMAP *,int);
106
+ static void ReturnObjectMatchAction(Environment *,OBJECT_MATCH_ACTION *);
107
+ static void ProcessObjectMatchQueue(Environment *);
108
+ static void MarkObjectPatternNetwork(Environment *,SLOT_BITMAP *);
109
+ static bool CompareSlotBitMaps(const SLOT_BITMAP *,const SLOT_BITMAP *);
110
+ static void ObjectPatternMatch(Environment *,size_t,size_t,OBJECT_PATTERN_NODE *,struct multifieldMarker *);
111
+ static void ProcessPatternNode(Environment *,size_t,size_t,OBJECT_PATTERN_NODE *,struct multifieldMarker *);
112
+ static void CreateObjectAlphaMatch(Environment *,OBJECT_ALPHA_NODE *);
113
+ static bool EvaluateObjectPatternTest(Environment *,size_t,struct multifieldMarker *,
114
+ Expression *,OBJECT_PATTERN_NODE *);
115
+ static void ObjectAssertAction(Environment *,Instance *);
116
+ static void ObjectModifyAction(Environment *,Instance *,SLOT_BITMAP *);
117
+ static void ObjectRetractAction(Environment *,Instance *,SLOT_BITMAP *);
118
+ static void ObjectPatternNetErrorMessage(Environment *,OBJECT_PATTERN_NODE *);
119
+ static void TraceErrorToObjectPattern(Environment *,bool,OBJECT_PATTERN_NODE *);
120
+
121
+ /* =========================================
122
+ *****************************************
123
+ EXTERNALLY VISIBLE FUNCTIONS
124
+ =========================================
125
+ ***************************************** */
126
+
127
+ /***************************************************************************
128
+ NAME : ObjectMatchDelay
129
+ DESCRIPTION : H/L interface for SetDelayObjectPatternMatching
130
+ INPUTS : None
131
+ RETURNS : Nothing useful
132
+ SIDE EFFECTS : DelayObjectPatternMatching set and Rete network updates
133
+ delayed until pattern-matching is completed
134
+ NOTES : H/L Syntax: (object-pattern-match-delay <action>*)
135
+ ***************************************************************************/
136
+ void ObjectMatchDelay(
137
+ Environment *theEnv,
138
+ UDFContext *context,
139
+ UDFValue *returnValue)
140
+ {
141
+ bool ov;
142
+
143
+ ov = SetDelayObjectPatternMatching(theEnv,true);
144
+
145
+ if (! UDFFirstArgument(context,ANY_TYPE_BITS,returnValue))
146
+ { return; }
147
+
148
+ if (EvaluationData(theEnv)->EvaluationError)
149
+ {
150
+ SetHaltExecution(theEnv,false);
151
+ SetEvaluationError(theEnv,false);
152
+ SetDelayObjectPatternMatching(theEnv,ov);
153
+ SetEvaluationError(theEnv,true);
154
+ }
155
+ else
156
+ SetDelayObjectPatternMatching(theEnv,ov);
157
+ }
158
+
159
+ /***************************************************
160
+ NAME : SetDelayObjectPatternMatching
161
+ DESCRIPTION : Sets the flag determining if Rete
162
+ network activity is to be delayed
163
+ for objects or not
164
+ INPUTS : The value of the flag
165
+ RETURNS : The old value of the flag
166
+ SIDE EFFECTS : DelayObjectPatternMatching set
167
+ NOTES : When the delay is set to false,
168
+ all pending Rete network updates
169
+ are performed
170
+ ***************************************************/
171
+ bool SetDelayObjectPatternMatching(
172
+ Environment *theEnv,
173
+ bool value)
174
+ {
175
+ bool oldval;
176
+
177
+ oldval = ObjectReteData(theEnv)->DelayObjectPatternMatching;
178
+ if (value)
179
+ ObjectReteData(theEnv)->DelayObjectPatternMatching = true;
180
+ else
181
+ {
182
+ ObjectReteData(theEnv)->DelayObjectPatternMatching = false;
183
+ ObjectNetworkAction(theEnv,0,NULL,-1);
184
+ }
185
+ return(oldval);
186
+ }
187
+
188
+ /***************************************************
189
+ NAME : GetDelayObjectPatternMatching
190
+ DESCRIPTION : Gets the flag determining if Rete
191
+ network activity is to be delayed
192
+ for objects or not
193
+ INPUTS : None
194
+ RETURNS : The flag
195
+ SIDE EFFECTS : None
196
+ NOTES : None
197
+ ***************************************************/
198
+ bool GetDelayObjectPatternMatching(
199
+ Environment *theEnv)
200
+ {
201
+ return(ObjectReteData(theEnv)->DelayObjectPatternMatching);
202
+ }
203
+
204
+ /********************************************************
205
+ NAME : ObjectNetworkPointer
206
+ DESCRIPTION : Returns the first object network
207
+ pattern node
208
+ INPUTS : None
209
+ RETURNS : The top of the object pattern network
210
+ SIDE EFFECTS : None
211
+ NOTES : None
212
+ ********************************************************/
213
+ OBJECT_PATTERN_NODE *ObjectNetworkPointer(
214
+ Environment *theEnv)
215
+ {
216
+ return(ObjectReteData(theEnv)->ObjectPatternNetworkPointer);
217
+ }
218
+
219
+ /********************************************************
220
+ NAME : ObjectNetworkTerminalPointer
221
+ DESCRIPTION : Returns the first terminal pattern node
222
+ INPUTS : None
223
+ RETURNS : The last node of a pattern
224
+ SIDE EFFECTS : None
225
+ NOTES : None
226
+ ********************************************************/
227
+ OBJECT_ALPHA_NODE *ObjectNetworkTerminalPointer(
228
+ Environment *theEnv)
229
+ {
230
+ return(ObjectReteData(theEnv)->ObjectPatternNetworkTerminalPointer);
231
+ }
232
+
233
+ /***************************************************
234
+ NAME : SetObjectNetworkPointer
235
+ DESCRIPTION : Sets the object pattern network to
236
+ the given network
237
+ INPUTS : Top of the new pattern network
238
+ RETURNS : Nothing useful
239
+ SIDE EFFECTS : ObjectPatternNetworkPointer set
240
+ NOTES : None
241
+ ***************************************************/
242
+ void SetObjectNetworkPointer(
243
+ Environment *theEnv,
244
+ OBJECT_PATTERN_NODE *value)
245
+ {
246
+ ObjectReteData(theEnv)->ObjectPatternNetworkPointer = value;
247
+ }
248
+
249
+ /*******************************************************
250
+ NAME : SetObjectNetworkTerminalPointer
251
+ DESCRIPTION : Sets the global list of terminal
252
+ pattern nodes (the ones containing
253
+ the bitmaps) to the given node
254
+ INPUTS : The last node of a pattern
255
+ RETURNS : Nothing useful
256
+ SIDE EFFECTS : ObjectPatternNetworkTerminalPointer set
257
+ NOTES : None
258
+ *******************************************************/
259
+ void SetObjectNetworkTerminalPointer(
260
+ Environment *theEnv,
261
+ OBJECT_ALPHA_NODE *value)
262
+ {
263
+ ObjectReteData(theEnv)->ObjectPatternNetworkTerminalPointer = value;
264
+ }
265
+
266
+ /************************************************************************
267
+ NAME : ObjectNetworkAction
268
+ DESCRIPTION : Main driver for pattern-matching on objects
269
+ If the pattern-matching is current delayed or another
270
+ object is currently being pattern-matched, the requested
271
+ match action is queued for later processing.
272
+ Otherwise, the match action is performed and the
273
+ Rete network is updated.
274
+ INPUTS : 1) The match action type
275
+ OBJECT_ASSERT (1)
276
+ OBJECT_RETRACT (2)
277
+ OBJECT_MODIFY (3)
278
+ 2) The instance to be matched (can be NULL if only
279
+ want pending actions to be performed)
280
+ 3) The name id of the slot being updated (can be -1)
281
+ If this argument is -1, it is assumed that any
282
+ pattern which could match this instance must be
283
+ checked. Otherwise, only the patterns which
284
+ explicitly match on the named slot will be checked.
285
+ RETURNS : Nothing useful
286
+ SIDE EFFECTS : Action queued or Rete network updated
287
+ NOTES : None
288
+ ************************************************************************/
289
+ void ObjectNetworkAction(
290
+ Environment *theEnv,
291
+ int type,
292
+ Instance *ins,
293
+ int slotNameID)
294
+ {
295
+ SLOT_BITMAP *tmpMap;
296
+
297
+ if (EngineData(theEnv)->JoinOperationInProgress)
298
+ return;
299
+
300
+ EngineData(theEnv)->JoinOperationInProgress = true;
301
+
302
+
303
+ /* ================================================
304
+ For purposes of conflict resolution, all objects
305
+ which have had pattern-matching delayed will
306
+ have the same relative timestamp, i.e., the
307
+ inference engine thinks they all just appeared
308
+ simultaneously
309
+
310
+ When delay is off, however, each object gets the
311
+ new and current timestamp as expected.
312
+ ================================================ */
313
+ ObjectReteData(theEnv)->UseEntityTimeTag = DefruleData(theEnv)->CurrentEntityTimeTag++;
314
+
315
+ /* ==================================================
316
+ If pattern-matching is delayed (by use of the
317
+ set-object-pattern-match-delay function), then
318
+ the instance should be marked for later processing
319
+ (when the delay is turned off).
320
+ ================================================== */
321
+ if (ins != NULL)
322
+ {
323
+ /* 6.05 Bug Fix */
324
+ ins->reteSynchronized = false;
325
+
326
+ if (ObjectReteData(theEnv)->DelayObjectPatternMatching == false)
327
+ switch (type)
328
+ {
329
+ case OBJECT_ASSERT :
330
+ ObjectAssertAction(theEnv,ins);
331
+ break;
332
+ case OBJECT_RETRACT :
333
+ ObjectRetractAction(theEnv,ins,NULL);
334
+ break;
335
+ default :
336
+ tmpMap = QueueModifySlotMap(theEnv,NULL,slotNameID);
337
+ ObjectModifyAction(theEnv,ins,tmpMap);
338
+ rm(theEnv,tmpMap,SlotBitMapSize(tmpMap));
339
+ }
340
+ else
341
+ QueueObjectMatchAction(theEnv,type,ins,slotNameID);
342
+ }
343
+
344
+ /* ========================================
345
+ Process all pending actions in the queue
346
+ All updates will use the same timestamp
347
+ ======================================== */
348
+ ProcessObjectMatchQueue(theEnv);
349
+
350
+ EngineData(theEnv)->JoinOperationInProgress = false;
351
+
352
+ ForceLogicalRetractions(theEnv);
353
+
354
+ /*=========================================*/
355
+ /* Free partial matches that were released */
356
+ /* by the assertion of the fact. */
357
+ /*=========================================*/
358
+
359
+ if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
360
+ }
361
+
362
+ /* =========================================
363
+ *****************************************
364
+ INTERNALLY VISIBLE FUNCTIONS
365
+ =========================================
366
+ ***************************************** */
367
+
368
+ /***************************************************
369
+ NAME : ResetObjectMatchTimeTags
370
+ DESCRIPTION : If CurrentObjectMatchTimeTag + 1
371
+ would cause an overflow,
372
+ CurrentObjectMatchTimeTag
373
+ is reset to 0L and all time tags
374
+ in object pattern nodes are reset.
375
+ INPUTS : None
376
+ RETURNS : Nothing useful
377
+ SIDE EFFECTS : CurrentObjectMatchTimeTag reset to
378
+ 0, and all match time tags reset
379
+ These tags are used to recognize
380
+ valid pattern nodes on a match
381
+ NOTES : None
382
+ ***************************************************/
383
+ void ResetObjectMatchTimeTags(
384
+ Environment *theEnv)
385
+ {
386
+ OBJECT_ALPHA_NODE *alphaPtr;
387
+ OBJECT_PATTERN_NODE *lastLevel;
388
+
389
+ /* ============================================
390
+ If the current tag incremented by one would
391
+ not cause an overflow, then we can leave
392
+ things alone.
393
+ ============================================ */
394
+ if ((ObjectReteData(theEnv)->CurrentObjectMatchTimeTag + 1L) > ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
395
+ return;
396
+ ObjectReteData(theEnv)->CurrentObjectMatchTimeTag = 0L;
397
+ alphaPtr = ObjectNetworkTerminalPointer(theEnv);
398
+ while (alphaPtr != NULL)
399
+ {
400
+ alphaPtr->matchTimeTag = 0L;
401
+ lastLevel = alphaPtr->patternNode;
402
+ while (lastLevel != NULL)
403
+ {
404
+ if (lastLevel->matchTimeTag == 0L)
405
+ break;
406
+ lastLevel->matchTimeTag = 0L;
407
+ lastLevel = lastLevel->lastLevel;
408
+ }
409
+ alphaPtr = alphaPtr->nxtTerminal;
410
+ }
411
+ }
412
+
413
+ /***************************************************
414
+ NAME : QueueObjectMatchAction
415
+ DESCRIPTION : Posts a Rete network match event
416
+ for later processing
417
+ INPUTS : 1) The match action type
418
+ OBJECT_ASSERT (1)
419
+ OBJECT_RETRACT (2)
420
+ OBJECT_MODIFY (3)
421
+ 2) The instance to be matched
422
+ 3) The name id of the slot being
423
+ updated (can be -1)
424
+ RETURNS : Nothing useful
425
+ SIDE EFFECTS : Queue updated
426
+ NOTES : None
427
+ ***************************************************/
428
+ static void QueueObjectMatchAction(
429
+ Environment *theEnv,
430
+ int type,
431
+ Instance *ins,
432
+ int slotNameID)
433
+ {
434
+ OBJECT_MATCH_ACTION *prv,*cur,*newMatch;
435
+ OBJECT_MATCH_ACTION *prvRetract = NULL; /* DR0873 */
436
+
437
+ prv = NULL;
438
+ cur = ObjectReteData(theEnv)->ObjectMatchActionQueue;
439
+ while (cur != NULL)
440
+ {
441
+ /* ===========================================================
442
+ Here are the possibilities for the first Rete event already
443
+ on the queue as compared with the new event for an object:
444
+
445
+ Assert/Retract --> Delete assert event
446
+ Ignore retract event
447
+ Assert/Modify --> Ignore modify event
448
+ Modify/Modify --> Merge new modify event
449
+ Modify/Retract --> Delete modify event
450
+ Queue the retract event
451
+ =========================================================== */
452
+ if (cur->ins == ins)
453
+ {
454
+ /* ===================================================
455
+ An action for initially asserting the newly created
456
+ object to all applicable patterns
457
+ =================================================== */
458
+ if (cur->type == OBJECT_ASSERT)
459
+ {
460
+ if (type == OBJECT_RETRACT)
461
+ {
462
+ /* ===================================================
463
+ If we are retracting the entire object, then we can
464
+ remove the assert action (and all modifies as well)
465
+ and ignore the retract action
466
+ (basically the object came and went before the Rete
467
+ network had a chance to see it)
468
+ =================================================== */
469
+ if (prv == NULL)
470
+ ObjectReteData(theEnv)->ObjectMatchActionQueue = cur->nxt;
471
+ else
472
+ prv->nxt = cur->nxt;
473
+ cur->ins->busy--;
474
+ ReturnObjectMatchAction(theEnv,cur);
475
+ }
476
+
477
+ /* =================================================
478
+ If this is a modify action, then we can ignore it
479
+ since the assert action will encompass it
480
+ ================================================= */
481
+ }
482
+
483
+ /* ===================================================
484
+ If the object is being deleted after a slot modify,
485
+ drop the modify event and replace with the retract
486
+ =================================================== */
487
+ else if (type == OBJECT_RETRACT)
488
+ {
489
+ cur->type = OBJECT_RETRACT;
490
+ if (cur->slotNameIDs != NULL)
491
+ {
492
+ rm(theEnv,cur->slotNameIDs,SlotBitMapSize(cur->slotNameIDs));
493
+ cur->slotNameIDs = NULL;
494
+ }
495
+ }
496
+
497
+ /* ====================================================
498
+ If a modify event for this slot is already on the
499
+ queue, ignore this one. Otherwise, merge the slot id
500
+ ==================================================== */
501
+ else
502
+ cur->slotNameIDs = QueueModifySlotMap(theEnv,cur->slotNameIDs,slotNameID);
503
+
504
+ return;
505
+ }
506
+
507
+ if (cur->type == OBJECT_RETRACT) /* DR0873 */
508
+ { prvRetract = cur; } /* DR0873 */
509
+ prv = cur;
510
+ cur = cur->nxt;
511
+ }
512
+
513
+ /* ================================================
514
+ If there are no actions for the instance already
515
+ on the queue, the new action is simply appended.
516
+ ================================================ */
517
+ newMatch = get_struct(theEnv,objectMatchAction);
518
+ newMatch->type = type;
519
+ newMatch->nxt = NULL; /* If we get here, cur should be NULL */
520
+ newMatch->slotNameIDs = (type != OBJECT_MODIFY) ? NULL :
521
+ QueueModifySlotMap(theEnv,NULL,slotNameID);
522
+ newMatch->ins = ins;
523
+ newMatch->ins->busy++;
524
+
525
+ /* DR0873 Begin */
526
+ /* Retract operations must be processed before assert and */
527
+ /* modify actions, otherwise the pattern matching process */
528
+ /* might attempt to access the slots of a retract instance. */
529
+
530
+ if (type == OBJECT_RETRACT)
531
+ {
532
+ if (prvRetract == NULL)
533
+ {
534
+ newMatch->nxt = ObjectReteData(theEnv)->ObjectMatchActionQueue;
535
+ ObjectReteData(theEnv)->ObjectMatchActionQueue = newMatch;
536
+ }
537
+ else
538
+ {
539
+ newMatch->nxt = prvRetract->nxt;
540
+ prvRetract->nxt = newMatch;
541
+ }
542
+ }
543
+ else
544
+ /* DR0873 End */
545
+
546
+ if (prv == NULL)
547
+ ObjectReteData(theEnv)->ObjectMatchActionQueue = newMatch;
548
+ else
549
+ prv->nxt = newMatch;
550
+ }
551
+
552
+ /****************************************************
553
+ NAME : QueueModifySlotMap
554
+ DESCRIPTION : Sets the bitmap for a queued
555
+ object modify Rete network action
556
+ INPUTS : 1) The old bitmap (can be NULL)
557
+ 2) The canonical slot id to set
558
+ RETURNS : The (new) bitmap
559
+ SIDE EFFECTS : Bitmap allocated/reallocated if
560
+ necessary, and slot id bit set
561
+ NOTES : If the bitmap must be (re)allocated,
562
+ this routine allocates twice the
563
+ room necessary for the current id
564
+ to allow for growth.
565
+ ****************************************************/
566
+ static SLOT_BITMAP *QueueModifySlotMap(
567
+ Environment *theEnv,
568
+ SLOT_BITMAP *oldMap,
569
+ int slotNameID)
570
+ {
571
+ SLOT_BITMAP *newMap;
572
+ unsigned short newmaxid;
573
+ unsigned oldsz,newsz;
574
+
575
+ if ((oldMap == NULL) ? true : (slotNameID > oldMap->maxid))
576
+ {
577
+ newmaxid = (unsigned short) (slotNameID * 2);
578
+ newsz = sizeof(SLOT_BITMAP) +
579
+ (sizeof(char) * (newmaxid / BITS_PER_BYTE));
580
+ newMap = (SLOT_BITMAP *) gm2(theEnv,newsz);
581
+ ClearBitString(newMap,newsz);
582
+ if (oldMap != NULL)
583
+ {
584
+ oldsz = SlotBitMapSize(oldMap);
585
+ GenCopyMemory(char,oldsz,newMap,oldMap);
586
+ rm(theEnv,oldMap,oldsz);
587
+ }
588
+ newMap->maxid = newmaxid;
589
+ }
590
+ else
591
+ newMap = oldMap;
592
+ SetBitMap(newMap->map,slotNameID);
593
+ return(newMap);
594
+ }
595
+
596
+ /***************************************************
597
+ NAME : ReturnObjectMatchAction
598
+ DESCRIPTION : Deallocates and object match action
599
+ structure and associated slot
600
+ bitmap (if any)
601
+ INPUTS : The queued match action item
602
+ RETURNS : Nothing useful
603
+ SIDE EFFECTS : Object match action item deleted
604
+ NOTES : None
605
+ ***************************************************/
606
+ static void ReturnObjectMatchAction(
607
+ Environment *theEnv,
608
+ OBJECT_MATCH_ACTION *omaPtr)
609
+ {
610
+ if (omaPtr->slotNameIDs != NULL)
611
+ rm(theEnv,omaPtr->slotNameIDs,SlotBitMapSize(omaPtr->slotNameIDs));
612
+ rtn_struct(theEnv,objectMatchAction,omaPtr);
613
+ }
614
+
615
+ /***************************************************
616
+ NAME : ProcessObjectMatchQueue
617
+ DESCRIPTION : Processes all outstanding object
618
+ Rete network update events
619
+ INPUTS : None
620
+ RETURNS : Nothing useful
621
+ SIDE EFFECTS : Pattern-matching on objects
622
+ NOTES : None
623
+ ***************************************************/
624
+ static void ProcessObjectMatchQueue(
625
+ Environment *theEnv)
626
+ {
627
+ OBJECT_MATCH_ACTION *cur;
628
+
629
+ while ((ObjectReteData(theEnv)->ObjectMatchActionQueue != NULL) &&
630
+ (ObjectReteData(theEnv)->DelayObjectPatternMatching == false))
631
+ {
632
+ cur = ObjectReteData(theEnv)->ObjectMatchActionQueue;
633
+ ObjectReteData(theEnv)->ObjectMatchActionQueue = cur->nxt;
634
+
635
+ switch(cur->type)
636
+ {
637
+ case OBJECT_ASSERT :
638
+ ObjectAssertAction(theEnv,cur->ins);
639
+ break;
640
+ case OBJECT_RETRACT :
641
+ ObjectRetractAction(theEnv,cur->ins,cur->slotNameIDs);
642
+ break;
643
+ default :
644
+ ObjectModifyAction(theEnv,cur->ins,cur->slotNameIDs);
645
+ }
646
+ cur->ins->busy--;
647
+ ReturnObjectMatchAction(theEnv,cur);
648
+ }
649
+ }
650
+
651
+ /******************************************************
652
+ NAME : MarkObjectPatternNetwork
653
+ DESCRIPTION : Iterates through all terminal
654
+ pattern nodes checking class and
655
+ slot bitmaps. If a pattern is
656
+ applicable to the object/slot change,
657
+ then all the nodes belonging to
658
+ the pattern are marked as needing
659
+ to be examined by the pattern matcher.
660
+ INPUTS : The bitmap of ids of the slots being
661
+ changed (NULL if this is an assert for the
662
+ for the entire object)
663
+ RETURNS : Nothing useful
664
+ SIDE EFFECTS : Applicable pattern nodes marked
665
+ NOTES : Incremental reset status is also
666
+ checked here
667
+ ******************************************************/
668
+ static void MarkObjectPatternNetwork(
669
+ Environment *theEnv,
670
+ SLOT_BITMAP *slotNameIDs)
671
+ {
672
+ OBJECT_ALPHA_NODE *alphaPtr;
673
+ OBJECT_PATTERN_NODE *upper;
674
+ Defclass *cls;
675
+ CLASS_ALPHA_LINK *current_alpha_link;
676
+
677
+ cls = ObjectReteData(theEnv)->CurrentPatternObject->cls;
678
+ current_alpha_link = cls->relevant_terminal_alpha_nodes;
679
+
680
+ ResetObjectMatchTimeTags(theEnv);
681
+ ObjectReteData(theEnv)->CurrentObjectMatchTimeTag++;
682
+
683
+ while (current_alpha_link != NULL)
684
+ {
685
+ alphaPtr = current_alpha_link->alphaNode;
686
+
687
+ /* =============================================================
688
+ If an incremental reset is in progress, make sure that the
689
+ pattern has been marked for initialization before proceeding.
690
+ ============================================================= */
691
+ #if (! RUN_TIME) && (! BLOAD_ONLY)
692
+ if (EngineData(theEnv)->IncrementalResetInProgress &&
693
+ (alphaPtr->header.initialize == false))
694
+ {
695
+ current_alpha_link = current_alpha_link->next;
696
+ continue;
697
+ }
698
+ #endif
699
+
700
+ /* ===================================================
701
+ If we are doing an assert, then we need to
702
+ check all patterns which satsify the class bitmap
703
+ (The retraction has already been done in this case)
704
+ =================================================== */
705
+ if (slotNameIDs == NULL)
706
+ {
707
+ alphaPtr->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag;
708
+
709
+ for (upper = alphaPtr->patternNode;
710
+ upper != NULL;
711
+ upper = upper->lastLevel)
712
+ {
713
+ if (upper->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
714
+ { break; }
715
+ else
716
+ { upper->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag; }
717
+ }
718
+ }
719
+
720
+ /* ===================================================
721
+ If we are doing a slot modify, then we need to
722
+ check only the subset of patterns which satisfy the
723
+ class bitmap AND actually match on the slot in
724
+ question.
725
+ =================================================== */
726
+ else if (alphaPtr->slotbmp != NULL)
727
+ {
728
+ if (CompareSlotBitMaps(slotNameIDs,
729
+ (const SLOT_BITMAP *) alphaPtr->slotbmp->contents))
730
+ {
731
+ alphaPtr->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag;
732
+ for (upper = alphaPtr->patternNode;
733
+ upper != NULL;
734
+ upper = upper->lastLevel)
735
+ {
736
+ if (upper->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
737
+ { break; }
738
+ else
739
+ { upper->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag; }
740
+ }
741
+ }
742
+ }
743
+
744
+ current_alpha_link = current_alpha_link->next;
745
+ }
746
+ }
747
+
748
+ /***************************************************
749
+ NAME : CompareSlotBitMaps
750
+ DESCRIPTION : Compares two slot bitmaps by
751
+ bitwising and'ing byte per byte up
752
+ to the length of the smaller map.
753
+ INPUTS : The two slot bitmaps
754
+ RETURNS : True if any common bits
755
+ are set in both maps, false
756
+ otherwise
757
+ SIDE EFFECTS : None
758
+ NOTES : None
759
+ ***************************************************/
760
+ static bool CompareSlotBitMaps(
761
+ const SLOT_BITMAP *smap1,
762
+ const SLOT_BITMAP *smap2)
763
+ {
764
+ unsigned short i, maxByte;
765
+
766
+ maxByte = (unsigned short)
767
+ (((smap1->maxid < smap2->maxid) ?
768
+ smap1->maxid : smap2->maxid) / BITS_PER_BYTE);
769
+ for (i = 0 ; i <= maxByte ; i++)
770
+ if (smap1->map[i] & smap2->map[i])
771
+ return true;
772
+ return false;
773
+ }
774
+
775
+ /**********************************************************************************
776
+ NAME : ObjectPatternMatch
777
+ DESCRIPTION : Iterates through all the pattern nodes on one level
778
+ in the pattern network. A node is only processed
779
+ if it can lead to a terminating class bitmap node
780
+ which applies to the object being matched. This
781
+ allows for a significant reduction in the number of
782
+ patterns considered.
783
+ INPUTS : 1) The offset of the slot position from the pattern index
784
+ 2) The pattern node being examined
785
+ 3) The end of the list of multifield markers for the pattern
786
+ RETURNS : Nothing useful
787
+ SIDE EFFECTS : The pattern tests are evaluated and the child nodes may
788
+ be processed (which may cause a whole series of Rete network
789
+ updates).
790
+ NOTES : Several globals are used to keep track of the current
791
+ slot being examined:
792
+ CurrentPatternMarks - the series of multifield markers
793
+ CurrentPatternObject - the object being pattern-matched
794
+ CurrentPatternObjectSlot - the current slot being examined
795
+ CurrentObjectSlotLength - the cardinality of the slot value
796
+
797
+ An optimization is performed when evaluating
798
+ constant tests on a slot value field. All
799
+ pattern nodes on a level which restrict the same slot
800
+ are grouped together. Those which are constant
801
+ tests are placed at the far right. Thus, as soon
802
+ as one of these constant tests succeeds, the remaining
803
+ nodes for that slot on this level can be skipped
804
+ **********************************************************************************/
805
+ static void ObjectPatternMatch(
806
+ Environment *theEnv,
807
+ size_t offset,
808
+ size_t multifieldsProcessed,
809
+ OBJECT_PATTERN_NODE *patternTop,
810
+ struct multifieldMarker *endMark)
811
+ {
812
+ size_t saveSlotLength;
813
+ InstanceSlot *saveSlot;
814
+ OBJECT_PATTERN_NODE *blockedNode;
815
+
816
+ while (patternTop != NULL)
817
+ {
818
+ /*=============================================================*/
819
+ /* MarkObjectPatternNetwork() has already marked pattern nodes */
820
+ /* which need processing according to the class bitmaps, slot */
821
+ /* updates and incremental reset status. */
822
+ /*=============================================================*/
823
+
824
+ if (patternTop->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
825
+ {
826
+ /*===========================================*/
827
+ /* Make sure we are examining the correct */
828
+ /* slot of the object for this pattern node. */
829
+ /*===========================================*/
830
+
831
+ if ((patternTop->slotNameID == ISA_ID) ||
832
+ (patternTop->slotNameID == NAME_ID))
833
+ {
834
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
835
+ ObjectReteData(theEnv)->CurrentObjectSlotLength = 1;
836
+ offset = 0;
837
+ }
838
+ else if ((ObjectReteData(theEnv)->CurrentPatternObjectSlot == NULL) ? true :
839
+ (ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->slotName->id != patternTop->slotNameID))
840
+ {
841
+ /*=======================================================*/
842
+ /* Need to reset the indices for the multifield */
843
+ /* markers now that we have moved onto a different slot. */
844
+ /*=======================================================*/
845
+
846
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot =
847
+ ObjectReteData(theEnv)->CurrentPatternObject->slotAddresses[ObjectReteData(theEnv)->CurrentPatternObject->cls->slotNameMap
848
+ [patternTop->slotNameID] - 1];
849
+ offset = 0;
850
+ if (ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->multiple)
851
+ ObjectReteData(theEnv)->CurrentObjectSlotLength =
852
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot->multifieldValue->length;
853
+ else
854
+ ObjectReteData(theEnv)->CurrentObjectSlotLength = 1;
855
+ }
856
+
857
+ /*==========================================================*/
858
+ /* Process the pattern node. If it is satisfied by the */
859
+ /* the instance, ProcessPatternNode() will recursively pass */
860
+ /* all of its children nodes through ObjectPatternMatch(). */
861
+ /*==========================================================*/
862
+
863
+ saveSlotLength = ObjectReteData(theEnv)->CurrentObjectSlotLength;
864
+ saveSlot = ObjectReteData(theEnv)->CurrentPatternObjectSlot;
865
+ ProcessPatternNode(theEnv,offset,multifieldsProcessed,patternTop,endMark);
866
+ ObjectReteData(theEnv)->CurrentObjectSlotLength = saveSlotLength;
867
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot = saveSlot;
868
+ }
869
+
870
+ /*============================================================*/
871
+ /* Move on to the siblings of this node - if the current node */
872
+ /* was a constant test that succeeded, skip further sibling */
873
+ /* nodes (which test on the same field in the pattern) which */
874
+ /* match on the same slot since they are all constant tests */
875
+ /* as well and will, of course fail. */
876
+ /*============================================================*/
877
+
878
+ if (patternTop->blocked == true)
879
+ {
880
+ patternTop->blocked = false;
881
+ blockedNode = patternTop;
882
+ patternTop = patternTop->rightNode;
883
+ while (patternTop != NULL)
884
+ {
885
+ if ((patternTop->slotNameID != blockedNode->slotNameID) ||
886
+ (patternTop->whichField != blockedNode->whichField))
887
+ break;
888
+ patternTop = patternTop->rightNode;
889
+ }
890
+ }
891
+ else
892
+ patternTop = patternTop->rightNode;
893
+ }
894
+ }
895
+
896
+ /**********************************************************************************
897
+ NAME : ProcessPatternNode
898
+ DESCRIPTION : Determines if a pattern node satsifies the corresponding
899
+ slot value field(s) in an object. If it does,
900
+ ObjectPatternMatch() is recursively called to process
901
+ the child nodes of this node. In this mutual recursion
902
+ between ObjectPatternMatch() and ProcessPatternNode(),
903
+ the nodes of all applicable patterns are processed
904
+ to completion. ObjectPatternMatch() enters an object
905
+ into a pattern's aplha memory when the traversal reaches
906
+ a terminal class bitmap node.
907
+ INPUTS : 1) The offset of the slot index from the pattern index
908
+ 2) The pattern node being examined
909
+ 3) The end of the list of multifield markers for the pattern
910
+ RETURNS : Nothing useful
911
+ SIDE EFFECTS : The pattern tests are evaluated and the child nodes may
912
+ be processed (which may cause a whole series of Rete network
913
+ updates).
914
+ NOTES : Several globals are used to keep track of the current
915
+ slot being examined:
916
+ CurrentPatternMarks - the series of multifield markers
917
+ CurrentPatternObject - the object being pattern-matched
918
+ CurrentPatternObjectSlot - the current slot being examined
919
+ CurrentObjectSlotLength - the cardinality of the slot value
920
+ **********************************************************************************/
921
+ static void ProcessPatternNode(
922
+ Environment *theEnv,
923
+ size_t offset,
924
+ size_t multifieldsProcessed,
925
+ OBJECT_PATTERN_NODE *patternNode,
926
+ struct multifieldMarker *endMark)
927
+ {
928
+ unsigned short patternSlotField;
929
+ size_t objectSlotField;
930
+ size_t objectSlotLength;
931
+ size_t repeatCount;
932
+ InstanceSlot *objectSlot;
933
+ struct multifieldMarker *newMark;
934
+ UDFValue theResult;
935
+ OBJECT_PATTERN_NODE *tempPtr;
936
+
937
+ patternSlotField = patternNode->whichField;
938
+
939
+ objectSlotField = patternSlotField + offset - multifieldsProcessed;
940
+
941
+ /*============================================*/
942
+ /* If this is a test on the class or the name */
943
+ /* of the object, process it separately. */
944
+ /*============================================*/
945
+
946
+ if (ObjectReteData(theEnv)->CurrentPatternObjectSlot == NULL)
947
+ {
948
+ if (patternNode->selector) /* TBD Necessary? */
949
+ {
950
+ if (EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,patternNode->networkTest->nextArg,patternNode))
951
+ {
952
+ EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
953
+
954
+ tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
955
+
956
+ if (tempPtr != NULL)
957
+ {
958
+ if (tempPtr->alphaNode != NULL)
959
+ { CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
960
+ ObjectPatternMatch(theEnv,offset,multifieldsProcessed,tempPtr->nextLevel,endMark);
961
+ }
962
+ }
963
+ }
964
+ else if ((patternNode->networkTest == NULL) ? true :
965
+ (EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,
966
+ (Expression *) patternNode->networkTest,patternNode)))
967
+ {
968
+ if (patternNode->alphaNode != NULL)
969
+ CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
970
+ ObjectPatternMatch(theEnv,offset,multifieldsProcessed,patternNode->nextLevel,endMark);
971
+ }
972
+ return;
973
+ }
974
+
975
+ /*===================================*/
976
+ /* Check a single-field restriction. */
977
+ /*===================================*/
978
+
979
+ if (patternNode->multifieldNode == 0)
980
+ {
981
+ if (patternNode->selector)
982
+ {
983
+ if (EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,patternNode->networkTest->nextArg,patternNode))
984
+ {
985
+ EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
986
+
987
+ tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
988
+
989
+ if (tempPtr != NULL)
990
+ {
991
+ if (tempPtr->alphaNode != NULL)
992
+ { CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
993
+ ObjectPatternMatch(theEnv,offset,multifieldsProcessed,tempPtr->nextLevel,endMark);
994
+ }
995
+ }
996
+ }
997
+ else if ((patternNode->networkTest == NULL) ? true :
998
+ EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,
999
+ (Expression *) patternNode->networkTest,patternNode))
1000
+ {
1001
+ if (patternNode->alphaNode != NULL)
1002
+ CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
1003
+ ObjectPatternMatch(theEnv,offset,multifieldsProcessed,patternNode->nextLevel,endMark);
1004
+ }
1005
+ return;
1006
+ }
1007
+
1008
+ /*==============================================================*/
1009
+ /* Check a multifield restriction. Add a marker for this field */
1010
+ /* which has indices indicating to which values in the object */
1011
+ /* slot the multifield pattern node is bound. */
1012
+ /*==============================================================*/
1013
+
1014
+ newMark = get_struct(theEnv,multifieldMarker);
1015
+ newMark->whichField = patternSlotField;
1016
+ newMark->where.whichSlot = (void *) ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->slotName->name;
1017
+ newMark->startPosition = objectSlotField;
1018
+
1019
+ newMark->next = NULL;
1020
+ if (ObjectReteData(theEnv)->CurrentPatternObjectMarks == NULL)
1021
+ ObjectReteData(theEnv)->CurrentPatternObjectMarks = newMark;
1022
+ else
1023
+ endMark->next = newMark;
1024
+
1025
+ /*============================================================*/
1026
+ /* If there are further pattern restrictions on this slot, */
1027
+ /* try pattern-matching for all possible bound values of the */
1028
+ /* multifield pattern node: from no values to all values from */
1029
+ /* the starting position of the multifield to the end of the */
1030
+ /* object slot. Otherwise, bind the multifield to all the */
1031
+ /* remaining fields in the slot value and continue with */
1032
+ /* pattern-matching. */
1033
+ /*============================================================*/
1034
+
1035
+ if (patternNode->endSlot == false)
1036
+ {
1037
+ objectSlotLength = ObjectReteData(theEnv)->CurrentObjectSlotLength;
1038
+ objectSlot = ObjectReteData(theEnv)->CurrentPatternObjectSlot;
1039
+ newMark->range = 0;
1040
+
1041
+ if ((objectSlotLength + 2) < (newMark->startPosition + patternNode->leaveFields))
1042
+ { repeatCount = 0; }
1043
+ else
1044
+ { repeatCount = objectSlotLength + 2 - newMark->startPosition - patternNode->leaveFields; }
1045
+
1046
+ while (repeatCount > 0)
1047
+ {
1048
+ if (patternNode->selector)
1049
+ {
1050
+ if (EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,patternNode->networkTest->nextArg,patternNode))
1051
+ {
1052
+ EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
1053
+
1054
+ tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
1055
+
1056
+ if (tempPtr != NULL)
1057
+ {
1058
+ if (tempPtr->alphaNode != NULL)
1059
+ { CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
1060
+ ObjectPatternMatch(theEnv,offset + newMark->startPosition + newMark->range - objectSlotField,
1061
+ multifieldsProcessed+1,tempPtr->nextLevel,newMark);
1062
+ ObjectReteData(theEnv)->CurrentObjectSlotLength = objectSlotLength;
1063
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot = objectSlot;
1064
+ }
1065
+ }
1066
+ }
1067
+ else if ((patternNode->networkTest == NULL) ? true :
1068
+ EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,
1069
+ (Expression *) patternNode->networkTest,patternNode))
1070
+ {
1071
+ if (patternNode->alphaNode != NULL)
1072
+ CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
1073
+ ObjectPatternMatch(theEnv,offset + newMark->startPosition + newMark->range - objectSlotField,
1074
+ multifieldsProcessed+1,patternNode->nextLevel,newMark);
1075
+ ObjectReteData(theEnv)->CurrentObjectSlotLength = objectSlotLength;
1076
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot = objectSlot;
1077
+ }
1078
+ newMark->range++;
1079
+ repeatCount--;
1080
+ }
1081
+ }
1082
+ else
1083
+ {
1084
+ newMark->range = ObjectReteData(theEnv)->CurrentObjectSlotLength + 1 - newMark->startPosition - patternNode->leaveFields;
1085
+ if (patternNode->selector)
1086
+ {
1087
+ if (EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,patternNode->networkTest->nextArg,patternNode))
1088
+ {
1089
+ EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
1090
+
1091
+ tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
1092
+
1093
+ if (tempPtr != NULL)
1094
+ {
1095
+ if (tempPtr->alphaNode != NULL)
1096
+ CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode);
1097
+ ObjectPatternMatch(theEnv,0,0,tempPtr->nextLevel,newMark);
1098
+ }
1099
+ }
1100
+ }
1101
+ else if ((patternNode->networkTest == NULL) ? true :
1102
+ EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,
1103
+ (Expression *) patternNode->networkTest,patternNode))
1104
+ {
1105
+ if (patternNode->alphaNode != NULL)
1106
+ CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
1107
+ ObjectPatternMatch(theEnv,0,0,patternNode->nextLevel,newMark);
1108
+ }
1109
+ }
1110
+
1111
+ /*=========================================*/
1112
+ /* Delete the temporary multifield marker. */
1113
+ /*=========================================*/
1114
+
1115
+ if (ObjectReteData(theEnv)->CurrentPatternObjectMarks == newMark)
1116
+ ObjectReteData(theEnv)->CurrentPatternObjectMarks = NULL;
1117
+ else
1118
+ endMark->next = NULL;
1119
+ rtn_struct(theEnv,multifieldMarker,newMark);
1120
+ }
1121
+
1122
+ /***************************************************
1123
+ NAME : CreateObjectAlphaMatch
1124
+ DESCRIPTION : Places an instance in the alpha
1125
+ memory of a pattern and drives the
1126
+ partial match through the join
1127
+ network
1128
+ INPUTS : The alpha memory node
1129
+ RETURNS : Nothing useful
1130
+ SIDE EFFECTS : Join network updated
1131
+ NOTES : None
1132
+ ***************************************************/
1133
+ static void CreateObjectAlphaMatch(
1134
+ Environment *theEnv,
1135
+ OBJECT_ALPHA_NODE *alphaPtr)
1136
+ {
1137
+ struct joinNode *listOfJoins;
1138
+ struct partialMatch *theMatch;
1139
+ struct patternMatch *newMatch;
1140
+ unsigned long hashValue;
1141
+
1142
+ while (alphaPtr != NULL)
1143
+ {
1144
+ if (alphaPtr->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
1145
+ {
1146
+ hashValue = ComputeRightHashValue(theEnv,&alphaPtr->header);
1147
+
1148
+ /* ===================================================
1149
+ If we have reached the class bitmap of the pattern,
1150
+ place the object in the alpha memory of each of
1151
+ the terminal nodes underneath and drive
1152
+ the partial matches through the join network.
1153
+
1154
+ Insert the instance into the alpha memory
1155
+ of this pattern and mark it as busy
1156
+ =================================================== */
1157
+ ObjectReteData(theEnv)->CurrentPatternObject->busy++;
1158
+ theMatch = CreateAlphaMatch(theEnv,ObjectReteData(theEnv)->CurrentPatternObject,
1159
+ ObjectReteData(theEnv)->CurrentPatternObjectMarks,
1160
+ (struct patternNodeHeader *) alphaPtr,hashValue);
1161
+ theMatch->owner = alphaPtr;
1162
+
1163
+ /* ======================================
1164
+ Attach the partial match to the object
1165
+ to ease later retraction
1166
+ ====================================== */
1167
+ newMatch = get_struct(theEnv,patternMatch);
1168
+ newMatch->next = (struct patternMatch *) ObjectReteData(theEnv)->CurrentPatternObject->partialMatchList;
1169
+ newMatch->matchingPattern = (struct patternNodeHeader *) alphaPtr;
1170
+ newMatch->theMatch = theMatch;
1171
+ ObjectReteData(theEnv)->CurrentPatternObject->partialMatchList = (void *) newMatch;
1172
+
1173
+ /* ================================================
1174
+ Drive the partial match through the join network
1175
+ ================================================ */
1176
+ listOfJoins = alphaPtr->header.entryJoin;
1177
+ while (listOfJoins != NULL)
1178
+ {
1179
+ NetworkAssert(theEnv,theMatch,listOfJoins);
1180
+ listOfJoins = listOfJoins->rightMatchNode;
1181
+ }
1182
+ }
1183
+ alphaPtr = alphaPtr->nxtInGroup;
1184
+ }
1185
+ }
1186
+
1187
+ /******************************************************
1188
+ NAME : EvaluateObjectPatternTest
1189
+ DESCRIPTION : Evaluates the pattern network test
1190
+ expression for a node
1191
+ INPUTS : 1) The actual index of the slot value
1192
+ field currently being examined
1193
+ 2) The multifield marker (if any)
1194
+ for the pattern node being exmained
1195
+ 3) The pattern network test expression
1196
+ 4) The pattern node being examined
1197
+ RETURNS : True if the node passes the
1198
+ test, false otherwise
1199
+ SIDE EFFECTS : Evaluation of the test
1200
+ EvaluationError and HaltExecution
1201
+ are always set to false
1202
+ NOTES : Assumes networkTest != NULL
1203
+ ******************************************************/
1204
+ static bool EvaluateObjectPatternTest(
1205
+ Environment *theEnv,
1206
+ size_t objectSlotField,
1207
+ struct multifieldMarker *selfSlotMarker,
1208
+ Expression *networkTest,
1209
+ OBJECT_PATTERN_NODE *patternNode)
1210
+ {
1211
+ UDFValue vresult;
1212
+ int rv;
1213
+
1214
+ if (networkTest == NULL) return true;
1215
+
1216
+ if (networkTest->type == OBJ_PN_CONSTANT)
1217
+ {
1218
+ struct expr *oldArgument;
1219
+
1220
+ oldArgument = EvaluationData(theEnv)->CurrentExpression;
1221
+ EvaluationData(theEnv)->CurrentExpression = networkTest;
1222
+ rv = ObjectCmpConstantFunction(theEnv,networkTest->value,&vresult);
1223
+ EvaluationData(theEnv)->CurrentExpression = oldArgument;
1224
+ if (rv)
1225
+ {
1226
+ if (((const struct ObjectCmpPNConstant *)
1227
+ networkTest->bitMapValue->contents)->pass)
1228
+ patternNode->blocked = true;
1229
+ return true;
1230
+ }
1231
+ return false;
1232
+ }
1233
+
1234
+ /* =========================================================
1235
+ Evaluate or expressions expressed in the format:
1236
+ (or <expression 1> <expression 2> ... <expression n>)
1237
+ Returns true (1.0) if any of the expression are true,
1238
+ otherwise returns false (0.0).
1239
+ ========================================================= */
1240
+ if (networkTest->value == ExpressionData(theEnv)->PTR_OR)
1241
+ {
1242
+ networkTest = networkTest->argList;
1243
+ while (networkTest != NULL)
1244
+ {
1245
+ if (EvaluateObjectPatternTest(theEnv,objectSlotField,selfSlotMarker,networkTest,patternNode))
1246
+ {
1247
+ /* ============================================
1248
+ A node can be blocked ONLY if there were one
1249
+ positive constant test on that node
1250
+ ============================================ */
1251
+ patternNode->blocked = false;
1252
+ return true;
1253
+ }
1254
+ patternNode->blocked = false;
1255
+ networkTest = networkTest->nextArg;
1256
+ }
1257
+ return false;
1258
+ }
1259
+
1260
+ /* ==========================================================
1261
+ Evaluate and expressions expressed in the format:
1262
+ (and <expression 1> <expression 2> ... <expression n>)
1263
+ Returns false if any of the expression are false,
1264
+ otherwise returns true.
1265
+ ========================================================== */
1266
+ else if (networkTest->value == ExpressionData(theEnv)->PTR_AND)
1267
+ {
1268
+ networkTest = networkTest->argList;
1269
+ while (networkTest != NULL)
1270
+ {
1271
+ if (EvaluateObjectPatternTest(theEnv,objectSlotField,selfSlotMarker,networkTest,patternNode)
1272
+ == false)
1273
+ {
1274
+ patternNode->blocked = false;
1275
+ return false;
1276
+ }
1277
+ patternNode->blocked = false;
1278
+ networkTest = networkTest->nextArg;
1279
+ }
1280
+ return true;
1281
+ }
1282
+
1283
+ /* =======================================================
1284
+ Evaluate all other expressions using EvaluateExpression
1285
+ ======================================================= */
1286
+ else
1287
+ {
1288
+ EvaluationData(theEnv)->HaltExecution = false;
1289
+ if (EvaluateExpression(theEnv,networkTest,&vresult))
1290
+ {
1291
+ ObjectPatternNetErrorMessage(theEnv,patternNode);
1292
+ EvaluationData(theEnv)->EvaluationError = false;
1293
+ EvaluationData(theEnv)->HaltExecution = false;
1294
+ return false;
1295
+ }
1296
+ if (vresult.value != FalseSymbol(theEnv))
1297
+ return true;
1298
+ }
1299
+ return false;
1300
+ }
1301
+
1302
+ /***************************************************
1303
+ NAME : ObjectAssertAction
1304
+ DESCRIPTION : Filters an instance through the
1305
+ object pattern network
1306
+ INPUTS : The instance
1307
+ RETURNS : Nothing useful
1308
+ SIDE EFFECTS : Instance matched
1309
+ NOTES : None
1310
+ ***************************************************/
1311
+ static void ObjectAssertAction(
1312
+ Environment *theEnv,
1313
+ Instance *ins)
1314
+ {
1315
+ ins->patternHeader.timeTag = ObjectReteData(theEnv)->UseEntityTimeTag;
1316
+ ObjectReteData(theEnv)->CurrentPatternObject = ins;
1317
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
1318
+ MarkObjectPatternNetwork(theEnv,NULL);
1319
+ ObjectPatternMatch(theEnv,0,0,ObjectNetworkPointer(theEnv),NULL);
1320
+ ins->reteSynchronized = true;
1321
+ }
1322
+
1323
+ /**********************************************************************
1324
+ NAME : ObjectModifyAction
1325
+ DESCRIPTION : Removes an instance from patterns (and attached joins)
1326
+ applicable to specified slot(s), and then filters
1327
+ same instance through object pattern network
1328
+ (only against patterns which explicitly match on
1329
+ named slot(s))
1330
+ INPUTS : 1) The instance
1331
+ 2) The bitmap of slot ids
1332
+ RETURNS : Nothing useful
1333
+ SIDE EFFECTS : Instance retracted/asserted
1334
+ NOTES : None
1335
+ **********************************************************************/
1336
+ static void ObjectModifyAction(
1337
+ Environment *theEnv,
1338
+ Instance *ins,
1339
+ SLOT_BITMAP *slotNameIDs)
1340
+ {
1341
+ ins->patternHeader.timeTag = ObjectReteData(theEnv)->UseEntityTimeTag;
1342
+ ObjectRetractAction(theEnv,ins,slotNameIDs);
1343
+ ObjectReteData(theEnv)->CurrentPatternObject = ins;
1344
+ ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
1345
+ MarkObjectPatternNetwork(theEnv,slotNameIDs);
1346
+ ObjectPatternMatch(theEnv,0,0,ObjectNetworkPointer(theEnv),NULL);
1347
+ ins->reteSynchronized = true;
1348
+ }
1349
+
1350
+ /****************************************************
1351
+ NAME : ObjectRetractAction
1352
+ DESCRIPTION : Retracts the instance from the
1353
+ applicable patterns for the object
1354
+ (if the slotNameID != -1, then the
1355
+ instance is only retracted from
1356
+ the alpha memories of the patterns
1357
+ which actually match on that slot)
1358
+ INPUTS : 1) The instance
1359
+ 2) The slot bitmap for a modify
1360
+ (NULL if the instance is actually
1361
+ being removed)
1362
+ RETURNS : Nothing useful
1363
+ SIDE EFFECTS : Retractions performed
1364
+ NOTES : None
1365
+ ****************************************************/
1366
+ static void ObjectRetractAction(
1367
+ Environment *theEnv,
1368
+ Instance *ins,
1369
+ SLOT_BITMAP *slotNameIDs)
1370
+ {
1371
+ struct patternMatch *prvMatch,*tmpMatch,
1372
+ *deleteMatch,*lastDeleteMatch;
1373
+ OBJECT_ALPHA_NODE *alphaPtr;
1374
+ void *saveDependents;
1375
+
1376
+ if (slotNameIDs == NULL)
1377
+ {
1378
+ if (ins->partialMatchList != NULL)
1379
+ {
1380
+ tmpMatch = (struct patternMatch *) ins->partialMatchList;
1381
+ while (tmpMatch != NULL)
1382
+ {
1383
+ ins->busy--;
1384
+ tmpMatch = tmpMatch->next;
1385
+ }
1386
+ NetworkRetract(theEnv,(struct patternMatch *) ins->partialMatchList);
1387
+ ins->partialMatchList = NULL;
1388
+ }
1389
+ }
1390
+ else
1391
+ {
1392
+ deleteMatch = NULL;
1393
+ lastDeleteMatch = NULL;
1394
+ prvMatch = NULL;
1395
+ tmpMatch = (struct patternMatch *) ins->partialMatchList;
1396
+ while (tmpMatch != NULL)
1397
+ {
1398
+ alphaPtr = (OBJECT_ALPHA_NODE *) tmpMatch->matchingPattern;
1399
+ if (alphaPtr->slotbmp != NULL)
1400
+ {
1401
+ if (CompareSlotBitMaps(slotNameIDs,
1402
+ (const SLOT_BITMAP *) alphaPtr->slotbmp->contents))
1403
+ {
1404
+ ins->busy--;
1405
+ if (prvMatch == NULL)
1406
+ ins->partialMatchList = (void *) tmpMatch->next;
1407
+ else
1408
+ prvMatch->next = tmpMatch->next;
1409
+ if (!deleteMatch)
1410
+ deleteMatch = tmpMatch;
1411
+ else
1412
+ lastDeleteMatch->next = tmpMatch;
1413
+ lastDeleteMatch = tmpMatch;
1414
+ tmpMatch = tmpMatch->next;
1415
+ lastDeleteMatch->next = NULL;
1416
+ }
1417
+ else
1418
+ {
1419
+ prvMatch = tmpMatch;
1420
+ tmpMatch = tmpMatch->next;
1421
+ }
1422
+ }
1423
+ else
1424
+ {
1425
+ prvMatch = tmpMatch;
1426
+ tmpMatch = tmpMatch->next;
1427
+ }
1428
+ }
1429
+
1430
+ /* =============================================
1431
+ We need to preserve any logical dependencies
1432
+ of this object and reattach them after doing
1433
+ the retract. Otherwise, the Rete network
1434
+ will believe the object is gone and remove
1435
+ the links from the partial matches upon which
1436
+ this object is logically dependent.
1437
+ ============================================= */
1438
+ if (deleteMatch != NULL)
1439
+ {
1440
+ saveDependents = ins->patternHeader.dependents;
1441
+ ins->patternHeader.dependents = NULL;
1442
+ NetworkRetract(theEnv,deleteMatch);
1443
+ ins->patternHeader.dependents = saveDependents;
1444
+ }
1445
+ }
1446
+
1447
+ if (ins->dataRemovalDeferred)
1448
+ {
1449
+ ins->dataRemovalDeferred = false;
1450
+ RemoveInstanceData(theEnv,ins);
1451
+ }
1452
+
1453
+ ins->reteSynchronized = true;
1454
+ }
1455
+
1456
+ /*****************************************************
1457
+ NAME : ObjectPatternNetErrorMessage
1458
+ DESCRIPTION : Prints out a locational error message
1459
+ when an evaluation error occurs
1460
+ during object pattern-matching
1461
+ INPUTS : The pattern node
1462
+ RETURNS : Nothing useful
1463
+ SIDE EFFECTS : Error message displayed
1464
+ NOTES : None
1465
+ *****************************************************/
1466
+ static void ObjectPatternNetErrorMessage(
1467
+ Environment *theEnv,
1468
+ OBJECT_PATTERN_NODE *patternPtr)
1469
+ {
1470
+ PrintErrorID(theEnv,"OBJRTMCH",1,true);
1471
+ WriteString(theEnv,STDERR,"This error occurred in the object pattern network\n");
1472
+ WriteString(theEnv,STDERR," Currently active instance: [");
1473
+ WriteString(theEnv,STDERR,ObjectReteData(theEnv)->CurrentPatternObject->name->contents);
1474
+ WriteString(theEnv,STDERR,"]\n");
1475
+ WriteString(theEnv,STDERR," Problem resides in slot '");
1476
+ WriteString(theEnv,STDERR,FindIDSlotName(theEnv,patternPtr->slotNameID)->contents);
1477
+ WriteString(theEnv,STDERR,"' field #");
1478
+ PrintUnsignedInteger(theEnv,STDERR,patternPtr->whichField);
1479
+ WriteString(theEnv,STDERR,"\n");
1480
+ TraceErrorToObjectPattern(theEnv,true,patternPtr);
1481
+ WriteString(theEnv,STDERR,"\n");
1482
+ }
1483
+
1484
+ /*********************************************************
1485
+ NAME : TraceErrorToObjectPattern
1486
+ DESCRIPTION : Used by ObjectPatternNetErrorMessage() to
1487
+ print the rule(s) which contain an object
1488
+ pattern.
1489
+ INPUTS : 1) A flag indicating if this is the
1490
+ node in which the error actually
1491
+ occurred or not
1492
+ 2) The pattern node
1493
+ RETURNS : Nothing useful
1494
+ SIDE EFFECTS : Error message displayed
1495
+ NOTES : None
1496
+ *********************************************************/
1497
+ static void TraceErrorToObjectPattern(
1498
+ Environment *theEnv,
1499
+ bool errorNode,
1500
+ OBJECT_PATTERN_NODE *patternPtr)
1501
+ {
1502
+ struct joinNode *joinPtr;
1503
+
1504
+ while (patternPtr != NULL)
1505
+ {
1506
+ if (patternPtr->alphaNode != NULL)
1507
+ {
1508
+ joinPtr = patternPtr->alphaNode->header.entryJoin;
1509
+ while (joinPtr != NULL)
1510
+ {
1511
+ TraceErrorToRule(theEnv,joinPtr," ");
1512
+ joinPtr = joinPtr->rightMatchNode;
1513
+ }
1514
+ }
1515
+ TraceErrorToObjectPattern(theEnv,false,patternPtr->nextLevel);
1516
+ if (errorNode)
1517
+ break;
1518
+ patternPtr = patternPtr->rightNode;
1519
+ }
1520
+
1521
+ }
1522
+
1523
+ #endif
1524
+