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,1191 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 10/01/16 */
5
+ /* */
6
+ /* DRIVE MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Handles join network activity associated with */
11
+ /* with the addition of a data entity such as a fact or */
12
+ /* instance. */
13
+ /* */
14
+ /* Principal Programmer(s): */
15
+ /* Gary D. Riley */
16
+ /* */
17
+ /* Contributing Programmer(s): */
18
+ /* */
19
+ /* Revision History: */
20
+ /* */
21
+ /* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
22
+ /* */
23
+ /* 6.24: Removed INCREMENTAL_RESET and */
24
+ /* LOGICAL_DEPENDENCIES compilation flags. */
25
+ /* */
26
+ /* Renamed BOOLEAN macro type to intBool. */
27
+ /* */
28
+ /* Rule with exists CE has incorrect activation. */
29
+ /* DR0867 */
30
+ /* */
31
+ /* 6.30: Added support for hashed memories. */
32
+ /* */
33
+ /* Added additional developer statistics to help */
34
+ /* analyze join network performance. */
35
+ /* */
36
+ /* Removed pseudo-facts used in not CE. */
37
+ /* */
38
+ /* 6.40: Added Env prefix to GetEvaluationError and */
39
+ /* SetEvaluationError functions. */
40
+ /* */
41
+ /* Pragma once and other inclusion changes. */
42
+ /* */
43
+ /* Added support for booleans with <stdbool.h>. */
44
+ /* */
45
+ /* Removed use of void pointers for specific */
46
+ /* data structures. */
47
+ /* */
48
+ /* UDF redesign. */
49
+ /* */
50
+ /*************************************************************/
51
+
52
+ #include <stdio.h>
53
+ #include <stdlib.h>
54
+
55
+ #include "setup.h"
56
+
57
+ #if DEFRULE_CONSTRUCT
58
+
59
+ #include "agenda.h"
60
+ #include "constant.h"
61
+ #include "engine.h"
62
+ #include "envrnmnt.h"
63
+ #include "incrrset.h"
64
+ #include "lgcldpnd.h"
65
+ #include "memalloc.h"
66
+ #include "prntutil.h"
67
+ #include "reteutil.h"
68
+ #include "retract.h"
69
+ #include "router.h"
70
+
71
+ #include "drive.h"
72
+
73
+ /***************************************/
74
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
75
+ /***************************************/
76
+
77
+ static void EmptyDrive(Environment *,struct joinNode *,struct partialMatch *,int);
78
+ static void JoinNetErrorMessage(Environment *,struct joinNode *);
79
+
80
+ /************************************************/
81
+ /* NetworkAssert: Primary routine for filtering */
82
+ /* a partial match through the join network. */
83
+ /************************************************/
84
+ void NetworkAssert(
85
+ Environment *theEnv,
86
+ struct partialMatch *binds,
87
+ struct joinNode *join)
88
+ {
89
+ /*=========================================================*/
90
+ /* If an incremental reset is being performed and the join */
91
+ /* is not part of the network to be reset, then return. */
92
+ /*=========================================================*/
93
+
94
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
95
+ if (EngineData(theEnv)->IncrementalResetInProgress && (join->initialize == false)) return;
96
+ #endif
97
+
98
+ /*==================================================*/
99
+ /* Use a special routine if this is the first join. */
100
+ /*==================================================*/
101
+
102
+ if (join->firstJoin)
103
+ {
104
+ EmptyDrive(theEnv,join,binds,NETWORK_ASSERT);
105
+ return;
106
+ }
107
+
108
+ /*================================*/
109
+ /* Enter the join from the right. */
110
+ /*================================*/
111
+
112
+ NetworkAssertRight(theEnv,binds,join,NETWORK_ASSERT);
113
+
114
+ return;
115
+ }
116
+
117
+ /*****************************************************/
118
+ /* NetworkAssertRight: Primary routine for filtering */
119
+ /* a partial match through the join network from */
120
+ /* the RHS of a join. */
121
+ /*****************************************************/
122
+ void NetworkAssertRight(
123
+ Environment *theEnv,
124
+ struct partialMatch *rhsBinds,
125
+ struct joinNode *join,
126
+ int operation)
127
+ {
128
+ struct partialMatch *lhsBinds, *nextBind;
129
+ bool exprResult, restore = false;
130
+ struct partialMatch *oldLHSBinds = NULL;
131
+ struct partialMatch *oldRHSBinds = NULL;
132
+ struct joinNode *oldJoin = NULL;
133
+
134
+ /*=========================================================*/
135
+ /* If an incremental reset is being performed and the join */
136
+ /* is not part of the network to be reset, then return. */
137
+ /*=========================================================*/
138
+
139
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
140
+ if (EngineData(theEnv)->IncrementalResetInProgress && (join->initialize == false)) return;
141
+ #endif
142
+
143
+ if (join->firstJoin)
144
+ {
145
+ EmptyDrive(theEnv,join,rhsBinds,operation);
146
+ return;
147
+ }
148
+
149
+ /*=====================================================*/
150
+ /* The partial matches entering from the LHS of a join */
151
+ /* are stored in the left beta memory of the join. */
152
+ /*=====================================================*/
153
+
154
+ lhsBinds = GetLeftBetaMemory(join,rhsBinds->hashValue);
155
+
156
+ #if DEVELOPER
157
+ if (lhsBinds != NULL)
158
+ { EngineData(theEnv)->rightToLeftLoops++; }
159
+ #endif
160
+
161
+ /*====================================*/
162
+ /* Set up the evaluation environment. */
163
+ /*====================================*/
164
+
165
+ if (lhsBinds != NULL)
166
+ {
167
+ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
168
+ oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
169
+ oldJoin = EngineData(theEnv)->GlobalJoin;
170
+ EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
171
+ EngineData(theEnv)->GlobalJoin = join;
172
+ restore = true;
173
+ }
174
+
175
+ /*===================================================*/
176
+ /* Compare each set of binds on the opposite side of */
177
+ /* the join with the set of binds that entered this */
178
+ /* join. If the binds don't mismatch, then perform */
179
+ /* the appropriate action for the logic of the join. */
180
+ /*===================================================*/
181
+
182
+ while (lhsBinds != NULL)
183
+ {
184
+ nextBind = lhsBinds->nextInMemory;
185
+ join->memoryCompares++;
186
+
187
+ /*===========================================================*/
188
+ /* Initialize some variables pointing to the partial matches */
189
+ /* in the LHS and RHS of the join. */
190
+ /*===========================================================*/
191
+
192
+ if (lhsBinds->hashValue != rhsBinds->hashValue)
193
+ {
194
+ #if DEVELOPER
195
+ if (join->leftMemory->size == 1)
196
+ { EngineData(theEnv)->betaHashListSkips++; }
197
+ else
198
+ { EngineData(theEnv)->betaHashHTSkips++; }
199
+
200
+ if (lhsBinds->marker != NULL)
201
+ { EngineData(theEnv)->unneededMarkerCompare++; }
202
+ #endif
203
+ lhsBinds = nextBind;
204
+ continue;
205
+ }
206
+
207
+ /*===============================================================*/
208
+ /* If there already is an associated RHS partial match stored in */
209
+ /* the LHS partial match from the beta memory of this join, then */
210
+ /* the exists/nand CE has already been satisfied and we can move */
211
+ /* on to the next partial match found in the beta memory. */
212
+ /*===============================================================*/
213
+
214
+ if (lhsBinds->marker != NULL)
215
+ {
216
+ #if DEVELOPER
217
+ EngineData(theEnv)->unneededMarkerCompare++;
218
+ #endif
219
+ lhsBinds = nextBind;
220
+ continue;
221
+ }
222
+
223
+ /*===================================================*/
224
+ /* If the join has no expression associated with it, */
225
+ /* then the new partial match derived from the LHS */
226
+ /* and RHS partial matches is valid. */
227
+ /*===================================================*/
228
+
229
+ if (join->networkTest == NULL)
230
+ { exprResult = true; }
231
+
232
+ /*=========================================================*/
233
+ /* If the join has an expression associated with it, then */
234
+ /* evaluate the expression to determine if the new partial */
235
+ /* match derived from the LHS and RHS partial matches is */
236
+ /* valid (i.e. variable bindings are consistent and */
237
+ /* predicate expressions evaluate to true). */
238
+ /*=========================================================*/
239
+
240
+ else
241
+ {
242
+ #if DEVELOPER
243
+ EngineData(theEnv)->rightToLeftComparisons++;
244
+ #endif
245
+ EngineData(theEnv)->GlobalLHSBinds = lhsBinds;
246
+ exprResult = EvaluateJoinExpression(theEnv,join->networkTest,join);
247
+ if (EvaluationData(theEnv)->EvaluationError)
248
+ {
249
+ if (join->patternIsNegated) exprResult = true;
250
+ SetEvaluationError(theEnv,false);
251
+ }
252
+
253
+ #if DEVELOPER
254
+ if (exprResult)
255
+ { EngineData(theEnv)->rightToLeftSucceeds++; }
256
+ #endif
257
+ }
258
+
259
+ if ((join->secondaryNetworkTest != NULL) && exprResult)
260
+ {
261
+ EngineData(theEnv)->GlobalLHSBinds = lhsBinds;
262
+ exprResult = EvaluateJoinExpression(theEnv,join->secondaryNetworkTest,join);
263
+ if (EvaluationData(theEnv)->EvaluationError)
264
+ { SetEvaluationError(theEnv,false); }
265
+ }
266
+
267
+ /*====================================================*/
268
+ /* If the join expression evaluated to true (i.e. */
269
+ /* there were no conflicts between variable bindings, */
270
+ /* all tests were satisfied, etc.), then perform the */
271
+ /* appropriate action given the logic of this join. */
272
+ /*====================================================*/
273
+
274
+ if (exprResult != false)
275
+ {
276
+ if (join->patternIsExists)
277
+ {
278
+ AddBlockedLink(lhsBinds,rhsBinds);
279
+ PPDrive(theEnv,lhsBinds,NULL,join,operation);
280
+ }
281
+ else if (join->patternIsNegated || join->joinFromTheRight)
282
+ {
283
+ AddBlockedLink(lhsBinds,rhsBinds);
284
+ if (lhsBinds->children != NULL)
285
+ { PosEntryRetractBeta(theEnv,lhsBinds,lhsBinds->children,operation); }
286
+ /*
287
+ if (lhsBinds->dependents != NULL)
288
+ { RemoveLogicalSupport(theEnv,lhsBinds); }
289
+ */
290
+ }
291
+ else
292
+ { PPDrive(theEnv,lhsBinds,rhsBinds,join,operation); }
293
+ }
294
+
295
+ /*====================================*/
296
+ /* Move on to the next partial match. */
297
+ /*====================================*/
298
+
299
+ lhsBinds = nextBind;
300
+ }
301
+
302
+ /*=========================================*/
303
+ /* Restore the old evaluation environment. */
304
+ /*=========================================*/
305
+
306
+ if (restore)
307
+ {
308
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
309
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
310
+ EngineData(theEnv)->GlobalJoin = oldJoin;
311
+ }
312
+
313
+ return;
314
+ }
315
+
316
+ /****************************************************/
317
+ /* NetworkAssertLeft: Primary routine for filtering */
318
+ /* a partial match through the join network when */
319
+ /* entering through the left side of a join. */
320
+ /****************************************************/
321
+ void NetworkAssertLeft(
322
+ Environment *theEnv,
323
+ struct partialMatch *lhsBinds,
324
+ struct joinNode *join,
325
+ int operation)
326
+ {
327
+ struct partialMatch *rhsBinds;
328
+ bool exprResult, restore = false;
329
+ unsigned long entryHashValue;
330
+ struct partialMatch *oldLHSBinds = NULL;
331
+ struct partialMatch *oldRHSBinds = NULL;
332
+ struct joinNode *oldJoin = NULL;
333
+
334
+ if ((operation == NETWORK_RETRACT) && PartialMatchWillBeDeleted(theEnv,lhsBinds))
335
+ { return; }
336
+
337
+ /*=========================================================*/
338
+ /* If an incremental reset is being performed and the join */
339
+ /* is not part of the network to be reset, then return. */
340
+ /*=========================================================*/
341
+
342
+ #if (! BLOAD_ONLY) && (! RUN_TIME)
343
+ if (EngineData(theEnv)->IncrementalResetInProgress && (join->initialize == false)) return;
344
+ #endif
345
+
346
+ /*===================================*/
347
+ /* The only action for the last join */
348
+ /* of a rule is to activate it. */
349
+ /*===================================*/
350
+
351
+ if (join->ruleToActivate != NULL)
352
+ {
353
+ AddActivation(theEnv,join->ruleToActivate,lhsBinds);
354
+ return;
355
+ }
356
+
357
+ /*=====================================*/
358
+ /* Handle a join handling a test CE at */
359
+ /* the beginning of a not/and group. */
360
+ /*=====================================*/
361
+
362
+ if (join->rightSideEntryStructure == NULL)
363
+ {
364
+ exprResult = true;
365
+
366
+ if (join->networkTest != NULL)
367
+ {
368
+ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
369
+ oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
370
+ oldJoin = EngineData(theEnv)->GlobalJoin;
371
+
372
+ EngineData(theEnv)->GlobalLHSBinds = lhsBinds;
373
+ EngineData(theEnv)->GlobalRHSBinds = NULL;
374
+ EngineData(theEnv)->GlobalJoin = join;
375
+
376
+ exprResult = EvaluateJoinExpression(theEnv,join->networkTest,join);
377
+ if (EvaluationData(theEnv)->EvaluationError)
378
+ { SetEvaluationError(theEnv,false); }
379
+
380
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
381
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
382
+ EngineData(theEnv)->GlobalJoin = oldJoin;
383
+ }
384
+
385
+ if (exprResult)
386
+ { PPDrive(theEnv,lhsBinds,NULL,join,operation); }
387
+
388
+ return;
389
+ }
390
+
391
+ /*==================================================*/
392
+ /* Initialize some variables used to indicate which */
393
+ /* side is being compared to the new partial match. */
394
+ /*==================================================*/
395
+
396
+ entryHashValue = lhsBinds->hashValue;
397
+ if (join->joinFromTheRight)
398
+ { rhsBinds = GetRightBetaMemory(join,entryHashValue); }
399
+ else
400
+ { rhsBinds = GetAlphaMemory(theEnv,(struct patternNodeHeader *) join->rightSideEntryStructure,entryHashValue); }
401
+
402
+ #if DEVELOPER
403
+ if (rhsBinds != NULL)
404
+ { EngineData(theEnv)->leftToRightLoops++; }
405
+ #endif
406
+
407
+ /*====================================*/
408
+ /* Set up the evaluation environment. */
409
+ /*====================================*/
410
+
411
+ if ((rhsBinds != NULL) || (join->secondaryNetworkTest != NULL))
412
+ {
413
+ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
414
+ oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
415
+ oldJoin = EngineData(theEnv)->GlobalJoin;
416
+ EngineData(theEnv)->GlobalLHSBinds = lhsBinds;
417
+ EngineData(theEnv)->GlobalJoin = join;
418
+ restore = true;
419
+ }
420
+
421
+ /*===================================================*/
422
+ /* Compare each set of binds on the opposite side of */
423
+ /* the join with the set of binds that entered this */
424
+ /* join. If the binds don't mismatch, then perform */
425
+ /* the appropriate action for the logic of the join. */
426
+ /*===================================================*/
427
+
428
+ while (rhsBinds != NULL)
429
+ {
430
+ if ((operation == NETWORK_RETRACT) && PartialMatchWillBeDeleted(theEnv,rhsBinds))
431
+ {
432
+ rhsBinds = rhsBinds->nextInMemory;
433
+ continue;
434
+ }
435
+
436
+ join->memoryCompares++;
437
+
438
+ /*===================================================*/
439
+ /* If the join has no expression associated with it, */
440
+ /* then the new partial match derived from the LHS */
441
+ /* and RHS partial matches is valid. */
442
+ /*===================================================*/
443
+
444
+ if (join->networkTest == NULL)
445
+ { exprResult = true; }
446
+
447
+ /*=========================================================*/
448
+ /* If the join has an expression associated with it, then */
449
+ /* evaluate the expression to determine if the new partial */
450
+ /* match derived from the LHS and RHS partial matches is */
451
+ /* valid (i.e. variable bindings are consistent and */
452
+ /* predicate expressions evaluate to true). */
453
+ /*=========================================================*/
454
+
455
+ else
456
+ {
457
+ #if DEVELOPER
458
+ EngineData(theEnv)->leftToRightComparisons++;
459
+ #endif
460
+ EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
461
+
462
+ exprResult = EvaluateJoinExpression(theEnv,join->networkTest,join);
463
+ if (EvaluationData(theEnv)->EvaluationError)
464
+ {
465
+ if (join->patternIsNegated) exprResult = true;
466
+ SetEvaluationError(theEnv,false);
467
+ }
468
+
469
+ #if DEVELOPER
470
+ if (exprResult)
471
+ { EngineData(theEnv)->leftToRightSucceeds++; }
472
+ #endif
473
+ }
474
+
475
+ // Bug Fix - Need to evaluate secondary network test for exists CE 0881
476
+
477
+ if ((join->secondaryNetworkTest != NULL) && exprResult && join->patternIsExists)
478
+ {
479
+ EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
480
+ exprResult = EvaluateJoinExpression(theEnv,join->secondaryNetworkTest,join);
481
+ if (EvaluationData(theEnv)->EvaluationError)
482
+ { SetEvaluationError(theEnv,false); }
483
+ }
484
+
485
+ /*====================================================*/
486
+ /* If the join expression evaluated to true (i.e. */
487
+ /* there were no conflicts between variable bindings, */
488
+ /* all tests were satisfied, etc.), then perform the */
489
+ /* appropriate action given the logic of this join. */
490
+ /*====================================================*/
491
+
492
+ if (exprResult != false)
493
+ {
494
+ /*==============================================*/
495
+ /* Use the PPDrive routine when the join isn't */
496
+ /* associated with a not CE and it doesn't have */
497
+ /* a join from the right. */
498
+ /*==============================================*/
499
+
500
+ if ((join->patternIsNegated == false) &&
501
+ (join->patternIsExists == false) &&
502
+ (join->joinFromTheRight == false))
503
+ { PPDrive(theEnv,lhsBinds,rhsBinds,join,operation); }
504
+
505
+ /*==================================================*/
506
+ /* At most, one partial match will be generated for */
507
+ /* a match from the right memory of an exists CE. */
508
+ /*==================================================*/
509
+
510
+ else if (join->patternIsExists)
511
+ {
512
+ AddBlockedLink(lhsBinds,rhsBinds);
513
+ PPDrive(theEnv,lhsBinds,NULL,join,operation);
514
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
515
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
516
+ EngineData(theEnv)->GlobalJoin = oldJoin;
517
+ return;
518
+ }
519
+
520
+ /*===========================================================*/
521
+ /* If the new partial match entered from the LHS of the join */
522
+ /* and the join is either associated with a not CE or the */
523
+ /* join has a join from the right, then mark the LHS partial */
524
+ /* match indicating that there is a RHS partial match */
525
+ /* preventing this join from being satisfied. Once this has */
526
+ /* happened, the other RHS partial matches don't have to be */
527
+ /* tested since it only takes one partial match to prevent */
528
+ /* the LHS from being satisfied. */
529
+ /*===========================================================*/
530
+
531
+ else
532
+ {
533
+ AddBlockedLink(lhsBinds,rhsBinds);
534
+ break;
535
+ }
536
+ }
537
+
538
+ /*====================================*/
539
+ /* Move on to the next partial match. */
540
+ /*====================================*/
541
+
542
+ rhsBinds = rhsBinds->nextInMemory;
543
+ }
544
+
545
+ /*==================================================================*/
546
+ /* If a join with an associated not CE or join from the right was */
547
+ /* entered from the LHS side of the join, and the join expression */
548
+ /* failed for all sets of matches for the new bindings on the LHS */
549
+ /* side (there was no RHS partial match preventing the LHS partial */
550
+ /* match from being satisfied), then the LHS partial match appended */
551
+ /* with an pseudo-fact that represents the instance of the not */
552
+ /* pattern or join from the right that was satisfied should be sent */
553
+ /* to the joins below this join. */
554
+ /*==================================================================*/
555
+
556
+ if ((join->patternIsNegated || join->joinFromTheRight) &&
557
+ (! join->patternIsExists) &&
558
+ (lhsBinds->marker == NULL))
559
+ {
560
+ if (join->secondaryNetworkTest != NULL)
561
+ {
562
+ EngineData(theEnv)->GlobalRHSBinds = NULL;
563
+
564
+ exprResult = EvaluateJoinExpression(theEnv,join->secondaryNetworkTest,join);
565
+ if (EvaluationData(theEnv)->EvaluationError)
566
+ { SetEvaluationError(theEnv,false); }
567
+
568
+ if (exprResult)
569
+ { PPDrive(theEnv,lhsBinds,NULL,join,operation); }
570
+ }
571
+ else
572
+ { PPDrive(theEnv,lhsBinds,NULL,join,operation); }
573
+ }
574
+
575
+ /*=========================================*/
576
+ /* Restore the old evaluation environment. */
577
+ /*=========================================*/
578
+
579
+ if (restore)
580
+ {
581
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
582
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
583
+ EngineData(theEnv)->GlobalJoin = oldJoin;
584
+ }
585
+
586
+ return;
587
+ }
588
+
589
+ /*******************************************************/
590
+ /* EvaluateJoinExpression: Evaluates join expressions. */
591
+ /* Performs a faster evaluation for join expressions */
592
+ /* than if EvaluateExpression was used directly. */
593
+ /*******************************************************/
594
+ bool EvaluateJoinExpression(
595
+ Environment *theEnv,
596
+ struct expr *joinExpr,
597
+ struct joinNode *joinPtr)
598
+ {
599
+ UDFValue theResult;
600
+ bool andLogic, result = true;
601
+
602
+ /*======================================*/
603
+ /* A NULL expression evaluates to true. */
604
+ /*======================================*/
605
+
606
+ if (joinExpr == NULL) return true;
607
+
608
+ /*====================================================*/
609
+ /* Initialize some variables which allow this routine */
610
+ /* to avoid calling the "and" and "or" functions if */
611
+ /* they are the first part of the expression to be */
612
+ /* evaluated. Most of the join expressions do not use */
613
+ /* deeply nested and/or functions so this technique */
614
+ /* speeds up evaluation. */
615
+ /*====================================================*/
616
+
617
+ if (joinExpr->value == ExpressionData(theEnv)->PTR_AND)
618
+ {
619
+ andLogic = true;
620
+ joinExpr = joinExpr->argList;
621
+ }
622
+ else if (joinExpr->value == ExpressionData(theEnv)->PTR_OR)
623
+ {
624
+ andLogic = false;
625
+ joinExpr = joinExpr->argList;
626
+ }
627
+ else
628
+ { andLogic = true; }
629
+
630
+ /*=========================================*/
631
+ /* Evaluate each of the expressions linked */
632
+ /* together in the join expression. */
633
+ /*=========================================*/
634
+
635
+ while (joinExpr != NULL)
636
+ {
637
+ /*================================*/
638
+ /* Evaluate a primitive function. */
639
+ /*================================*/
640
+
641
+ if ((EvaluationData(theEnv)->PrimitivesArray[joinExpr->type] == NULL) ?
642
+ false :
643
+ EvaluationData(theEnv)->PrimitivesArray[joinExpr->type]->evaluateFunction != NULL)
644
+ {
645
+ struct expr *oldArgument;
646
+
647
+ oldArgument = EvaluationData(theEnv)->CurrentExpression;
648
+ EvaluationData(theEnv)->CurrentExpression = joinExpr;
649
+ result = (*EvaluationData(theEnv)->PrimitivesArray[joinExpr->type]->evaluateFunction)(theEnv,joinExpr->value,&theResult);
650
+ EvaluationData(theEnv)->CurrentExpression = oldArgument;
651
+ }
652
+
653
+ /*=============================*/
654
+ /* Evaluate the "or" function. */
655
+ /*=============================*/
656
+
657
+ else if (joinExpr->value == ExpressionData(theEnv)->PTR_OR)
658
+ {
659
+ result = false;
660
+ if (EvaluateJoinExpression(theEnv,joinExpr,joinPtr) == true)
661
+ {
662
+ if (EvaluationData(theEnv)->EvaluationError)
663
+ { return false; }
664
+ result = true;
665
+ }
666
+ else if (EvaluationData(theEnv)->EvaluationError)
667
+ { return false; }
668
+ }
669
+
670
+ /*==============================*/
671
+ /* Evaluate the "and" function. */
672
+ /*==============================*/
673
+
674
+ else if (joinExpr->value == ExpressionData(theEnv)->PTR_AND)
675
+ {
676
+ result = true;
677
+ if (EvaluateJoinExpression(theEnv,joinExpr,joinPtr) == false)
678
+ {
679
+ if (EvaluationData(theEnv)->EvaluationError)
680
+ { return false; }
681
+ result = false;
682
+ }
683
+ else if (EvaluationData(theEnv)->EvaluationError)
684
+ { return false; }
685
+ }
686
+
687
+ /*==========================================================*/
688
+ /* Evaluate all other expressions using EvaluateExpression. */
689
+ /*==========================================================*/
690
+
691
+ else
692
+ {
693
+ EvaluateExpression(theEnv,joinExpr,&theResult);
694
+
695
+ if (EvaluationData(theEnv)->EvaluationError)
696
+ {
697
+ JoinNetErrorMessage(theEnv,joinPtr);
698
+ return false;
699
+ }
700
+
701
+ if (theResult.value == FalseSymbol(theEnv))
702
+ { result = false; }
703
+ else
704
+ { result = true; }
705
+ }
706
+
707
+ /*====================================*/
708
+ /* Handle the short cut evaluation of */
709
+ /* the "and" and "or" functions. */
710
+ /*====================================*/
711
+
712
+ if ((andLogic == true) && (result == false))
713
+ { return false; }
714
+ else if ((andLogic == false) && (result == true))
715
+ { return true; }
716
+
717
+ /*==============================================*/
718
+ /* Move to the next expression to be evaluated. */
719
+ /*==============================================*/
720
+
721
+ joinExpr = joinExpr->nextArg;
722
+ }
723
+
724
+ /*=================================================*/
725
+ /* Return the result of evaluating the expression. */
726
+ /*=================================================*/
727
+
728
+ return(result);
729
+ }
730
+
731
+ /*********************************/
732
+ /* EvaluateSecondaryNetworkTest: */
733
+ /*********************************/
734
+ bool EvaluateSecondaryNetworkTest(
735
+ Environment *theEnv,
736
+ struct partialMatch *leftMatch,
737
+ struct joinNode *joinPtr)
738
+ {
739
+ bool joinExpr;
740
+ struct partialMatch *oldLHSBinds;
741
+ struct partialMatch *oldRHSBinds;
742
+ struct joinNode *oldJoin;
743
+
744
+ if (joinPtr->secondaryNetworkTest == NULL)
745
+ { return true; }
746
+
747
+ #if DEVELOPER
748
+ EngineData(theEnv)->rightToLeftComparisons++;
749
+ #endif
750
+ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
751
+ oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
752
+ oldJoin = EngineData(theEnv)->GlobalJoin;
753
+ EngineData(theEnv)->GlobalLHSBinds = leftMatch;
754
+ EngineData(theEnv)->GlobalRHSBinds = NULL;
755
+ EngineData(theEnv)->GlobalJoin = joinPtr;
756
+
757
+ joinExpr = EvaluateJoinExpression(theEnv,joinPtr->secondaryNetworkTest,joinPtr);
758
+ EvaluationData(theEnv)->EvaluationError = false;
759
+
760
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
761
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
762
+ EngineData(theEnv)->GlobalJoin = oldJoin;
763
+
764
+ return(joinExpr);
765
+ }
766
+
767
+ /************************/
768
+ /* BetaMemoryHashValue: */
769
+ /************************/
770
+ unsigned long BetaMemoryHashValue(
771
+ Environment *theEnv,
772
+ struct expr *hashExpr,
773
+ struct partialMatch *lbinds,
774
+ struct partialMatch *rbinds,
775
+ struct joinNode *joinPtr)
776
+ {
777
+ UDFValue theResult;
778
+ struct partialMatch *oldLHSBinds;
779
+ struct partialMatch *oldRHSBinds;
780
+ struct joinNode *oldJoin;
781
+ unsigned long hashValue = 0;
782
+ unsigned long multiplier = 1;
783
+ union
784
+ {
785
+ void *vv;
786
+ unsigned long liv;
787
+ } fis;
788
+
789
+ /*======================================*/
790
+ /* A NULL expression evaluates to zero. */
791
+ /*======================================*/
792
+
793
+ if (hashExpr == NULL)
794
+ { return 0; }
795
+
796
+ /*=========================================*/
797
+ /* Initialize some of the global variables */
798
+ /* used when evaluating expressions. */
799
+ /*=========================================*/
800
+
801
+ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
802
+ oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
803
+ oldJoin = EngineData(theEnv)->GlobalJoin;
804
+ EngineData(theEnv)->GlobalLHSBinds = lbinds;
805
+ EngineData(theEnv)->GlobalRHSBinds = rbinds;
806
+ EngineData(theEnv)->GlobalJoin = joinPtr;
807
+
808
+ /*=========================================*/
809
+ /* Evaluate each of the expressions linked */
810
+ /* together in the join expression. */
811
+ /*=========================================*/
812
+
813
+ while (hashExpr != NULL)
814
+ {
815
+ /*================================*/
816
+ /* Evaluate a primitive function. */
817
+ /*================================*/
818
+
819
+ if ((EvaluationData(theEnv)->PrimitivesArray[hashExpr->type] == NULL) ?
820
+ false :
821
+ EvaluationData(theEnv)->PrimitivesArray[hashExpr->type]->evaluateFunction != NULL)
822
+ {
823
+ struct expr *oldArgument;
824
+
825
+ oldArgument = EvaluationData(theEnv)->CurrentExpression;
826
+ EvaluationData(theEnv)->CurrentExpression = hashExpr;
827
+ (*EvaluationData(theEnv)->PrimitivesArray[hashExpr->type]->evaluateFunction)(theEnv,hashExpr->value,&theResult);
828
+ EvaluationData(theEnv)->CurrentExpression = oldArgument;
829
+ }
830
+
831
+ /*==========================================================*/
832
+ /* Evaluate all other expressions using EvaluateExpression. */
833
+ /*==========================================================*/
834
+
835
+ else
836
+ { EvaluateExpression(theEnv,hashExpr,&theResult); }
837
+
838
+ switch (theResult.header->type)
839
+ {
840
+ case STRING_TYPE:
841
+ case SYMBOL_TYPE:
842
+ case INSTANCE_NAME_TYPE:
843
+ hashValue += theResult.lexemeValue->bucket * multiplier;
844
+ break;
845
+
846
+ case INTEGER_TYPE:
847
+ hashValue += (theResult.integerValue->bucket * multiplier);
848
+ break;
849
+
850
+ case FLOAT_TYPE:
851
+ hashValue += (theResult.floatValue->bucket * multiplier);
852
+ break;
853
+
854
+ case FACT_ADDRESS_TYPE:
855
+ #if OBJECT_SYSTEM
856
+ case INSTANCE_ADDRESS_TYPE:
857
+ #endif
858
+ fis.liv = 0;
859
+ fis.vv = theResult.value;
860
+ hashValue += fis.liv * multiplier;
861
+ break;
862
+
863
+ case EXTERNAL_ADDRESS_TYPE:
864
+ fis.liv = 0;
865
+ fis.vv = theResult.externalAddressValue->contents;
866
+ hashValue += fis.liv * multiplier;
867
+ break;
868
+ }
869
+
870
+ /*==============================================*/
871
+ /* Move to the next expression to be evaluated. */
872
+ /*==============================================*/
873
+
874
+ hashExpr = hashExpr->nextArg;
875
+ multiplier = multiplier * 509;
876
+ }
877
+
878
+ /*=======================================*/
879
+ /* Restore some of the global variables. */
880
+ /*=======================================*/
881
+
882
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
883
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
884
+ EngineData(theEnv)->GlobalJoin = oldJoin;
885
+
886
+ /*=================================================*/
887
+ /* Return the result of evaluating the expression. */
888
+ /*=================================================*/
889
+
890
+ return hashValue;
891
+ }
892
+
893
+ /*******************************************************************/
894
+ /* PPDrive: Handles the merging of an alpha memory partial match */
895
+ /* with a beta memory partial match for a join that has positive */
896
+ /* LHS entry and positive RHS entry. The partial matches being */
897
+ /* merged have previously been checked to determine that they */
898
+ /* satisify the constraints for the join. Once merged, the new */
899
+ /* partial match is sent to each child join of the join from */
900
+ /* which the merge took place. */
901
+ /*******************************************************************/
902
+ void PPDrive(
903
+ Environment *theEnv,
904
+ struct partialMatch *lhsBinds,
905
+ struct partialMatch *rhsBinds,
906
+ struct joinNode *join,
907
+ int operation)
908
+ {
909
+ struct partialMatch *linker;
910
+ struct joinLink *listOfJoins;
911
+ unsigned long hashValue;
912
+
913
+ /*================================================*/
914
+ /* Send the new partial match to all child joins. */
915
+ /*================================================*/
916
+
917
+ listOfJoins = join->nextLinks;
918
+ if (listOfJoins == NULL) return;
919
+
920
+ /*===============================================================*/
921
+ /* In the current implementation, all children of this join must */
922
+ /* be entered from the same side (either all left or all right). */
923
+ /*===============================================================*/
924
+
925
+ while (listOfJoins != NULL)
926
+ {
927
+ /*==================================================*/
928
+ /* Merge the alpha and beta memory partial matches. */
929
+ /*==================================================*/
930
+
931
+ linker = MergePartialMatches(theEnv,lhsBinds,rhsBinds);
932
+
933
+ /*================================================*/
934
+ /* Determine the hash value of the partial match. */
935
+ /*================================================*/
936
+
937
+ if (listOfJoins->enterDirection == LHS)
938
+ {
939
+ if (listOfJoins->join->leftHash != NULL)
940
+ { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->leftHash,linker,NULL,listOfJoins->join); }
941
+ else
942
+ { hashValue = 0; }
943
+ }
944
+ else
945
+ {
946
+ if (listOfJoins->join->rightHash != NULL)
947
+ { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->rightHash,linker,NULL,listOfJoins->join); }
948
+ else
949
+ { hashValue = 0; }
950
+ }
951
+
952
+ /*=======================================================*/
953
+ /* Add the partial match to the beta memory of the join. */
954
+ /*=======================================================*/
955
+
956
+ UpdateBetaPMLinks(theEnv,linker,lhsBinds,rhsBinds,listOfJoins->join,hashValue,listOfJoins->enterDirection);
957
+
958
+ if (listOfJoins->enterDirection == LHS)
959
+ { NetworkAssertLeft(theEnv,linker,listOfJoins->join,operation); }
960
+ else
961
+ { NetworkAssertRight(theEnv,linker,listOfJoins->join,operation); }
962
+
963
+ listOfJoins = listOfJoins->next;
964
+ }
965
+
966
+ return;
967
+ }
968
+
969
+ /***********************************************************************/
970
+ /* EPMDrive: Drives an empty partial match to the next level of joins. */
971
+ /* An empty partial match is usually associated with a negated CE */
972
+ /* that is the first CE of a rule. */
973
+ /***********************************************************************/
974
+ void EPMDrive(
975
+ Environment *theEnv,
976
+ struct partialMatch *parent,
977
+ struct joinNode *join,
978
+ int operation)
979
+ {
980
+ struct partialMatch *linker;
981
+ struct joinLink *listOfJoins;
982
+
983
+ listOfJoins = join->nextLinks;
984
+ if (listOfJoins == NULL) return;
985
+
986
+ while (listOfJoins != NULL)
987
+ {
988
+ linker = CreateEmptyPartialMatch(theEnv);
989
+
990
+ UpdateBetaPMLinks(theEnv,linker,parent,NULL,listOfJoins->join,0,listOfJoins->enterDirection);
991
+
992
+ if (listOfJoins->enterDirection == LHS)
993
+ { NetworkAssertLeft(theEnv,linker,listOfJoins->join,operation); }
994
+ else
995
+ { NetworkAssertRight(theEnv,linker,listOfJoins->join,operation); }
996
+
997
+ listOfJoins = listOfJoins->next;
998
+ }
999
+ }
1000
+
1001
+ /***************************************************************/
1002
+ /* EmptyDrive: Handles the entry of a alpha memory partial */
1003
+ /* match from the RHS of a join that is the first join of */
1004
+ /* a rule (i.e. a join that cannot be entered from the LHS). */
1005
+ /***************************************************************/
1006
+ static void EmptyDrive(
1007
+ Environment *theEnv,
1008
+ struct joinNode *join,
1009
+ struct partialMatch *rhsBinds,
1010
+ int operation)
1011
+ {
1012
+ struct partialMatch *linker, *existsParent = NULL, *notParent;
1013
+ struct joinLink *listOfJoins;
1014
+ bool joinExpr;
1015
+ unsigned long hashValue;
1016
+ struct partialMatch *oldLHSBinds;
1017
+ struct partialMatch *oldRHSBinds;
1018
+ struct joinNode *oldJoin;
1019
+
1020
+ /*======================================================*/
1021
+ /* Determine if the alpha memory partial match satifies */
1022
+ /* the join expression. If it doesn't then no further */
1023
+ /* action is taken. */
1024
+ /*======================================================*/
1025
+
1026
+ if (join->networkTest != NULL)
1027
+ {
1028
+
1029
+ #if DEVELOPER
1030
+ EngineData(theEnv)->rightToLeftComparisons++;
1031
+ #endif
1032
+ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
1033
+ oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
1034
+ oldJoin = EngineData(theEnv)->GlobalJoin;
1035
+ EngineData(theEnv)->GlobalLHSBinds = NULL;
1036
+ EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
1037
+ EngineData(theEnv)->GlobalJoin = join;
1038
+
1039
+ joinExpr = EvaluateJoinExpression(theEnv,join->networkTest,join);
1040
+ EvaluationData(theEnv)->EvaluationError = false;
1041
+
1042
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
1043
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
1044
+ EngineData(theEnv)->GlobalJoin = oldJoin;
1045
+
1046
+ if (joinExpr == false) return;
1047
+ }
1048
+
1049
+ if (join->secondaryNetworkTest != NULL)
1050
+ {
1051
+ #if DEVELOPER
1052
+ EngineData(theEnv)->rightToLeftComparisons++;
1053
+ #endif
1054
+ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
1055
+ oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
1056
+ oldJoin = EngineData(theEnv)->GlobalJoin;
1057
+ EngineData(theEnv)->GlobalLHSBinds = NULL;
1058
+ EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
1059
+ EngineData(theEnv)->GlobalJoin = join;
1060
+
1061
+ joinExpr = EvaluateJoinExpression(theEnv,join->secondaryNetworkTest,join);
1062
+ EvaluationData(theEnv)->EvaluationError = false;
1063
+
1064
+ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
1065
+ EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
1066
+ EngineData(theEnv)->GlobalJoin = oldJoin;
1067
+
1068
+ if (joinExpr == false) return;
1069
+ }
1070
+
1071
+ /*========================================================*/
1072
+ /* Handle a negated first pattern or join from the right. */
1073
+ /*========================================================*/
1074
+
1075
+ if (join->patternIsNegated || (join->joinFromTheRight && (! join->patternIsExists))) /* reorder to remove patternIsExists test */
1076
+ {
1077
+ notParent = join->leftMemory->beta[0];
1078
+ if (notParent->marker != NULL)
1079
+ { return; }
1080
+
1081
+ AddBlockedLink(notParent,rhsBinds);
1082
+
1083
+ if (notParent->children != NULL)
1084
+ { PosEntryRetractBeta(theEnv,notParent,notParent->children,operation); }
1085
+ /*
1086
+ if (notParent->dependents != NULL)
1087
+ { RemoveLogicalSupport(theEnv,notParent); }
1088
+ */
1089
+
1090
+ return;
1091
+ }
1092
+
1093
+ /*=====================================================*/
1094
+ /* For exists CEs used as the first pattern of a rule, */
1095
+ /* a special partial match in the left memory of the */
1096
+ /* join is used to track the RHS partial match */
1097
+ /* satisfying the CE. */
1098
+ /*=====================================================*/
1099
+ /* TBD reorder */
1100
+ if (join->patternIsExists)
1101
+ {
1102
+ existsParent = join->leftMemory->beta[0];
1103
+ if (existsParent->marker != NULL)
1104
+ { return; }
1105
+ AddBlockedLink(existsParent,rhsBinds);
1106
+ }
1107
+
1108
+ /*============================================*/
1109
+ /* Send the partial match to all child joins. */
1110
+ /*============================================*/
1111
+
1112
+ listOfJoins = join->nextLinks;
1113
+ if (listOfJoins == NULL) return;
1114
+
1115
+ while (listOfJoins != NULL)
1116
+ {
1117
+ /*===================================================================*/
1118
+ /* An exists CE as the first pattern of a rule can generate at most */
1119
+ /* one partial match, so if there's already a partial match in the */
1120
+ /* beta memory nothing further needs to be done. Since there are no */
1121
+ /* variable bindings which child joins can use for indexing, the */
1122
+ /* partial matches will always be stored in the bucket with index 0. */
1123
+ /* Although an exists is associated with a specific fact/instance */
1124
+ /* (through its rightParent link) that allows it to be satisfied, */
1125
+ /* the bindings in the partial match will be empty for this CE. */
1126
+ /*===================================================================*/
1127
+
1128
+ if (join->patternIsExists)
1129
+ { linker = CreateEmptyPartialMatch(theEnv); }
1130
+
1131
+ /*=============================================================*/
1132
+ /* Othewise just copy the partial match from the alpha memory. */
1133
+ /*=============================================================*/
1134
+
1135
+ else
1136
+ { linker = CopyPartialMatch(theEnv,rhsBinds); }
1137
+
1138
+ /*================================================*/
1139
+ /* Determine the hash value of the partial match. */
1140
+ /*================================================*/
1141
+
1142
+ if (listOfJoins->enterDirection == LHS)
1143
+ {
1144
+ if (listOfJoins->join->leftHash != NULL)
1145
+ { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->leftHash,linker,NULL,listOfJoins->join); }
1146
+ else
1147
+ { hashValue = 0; }
1148
+ }
1149
+ else
1150
+ {
1151
+ if (listOfJoins->join->rightHash != NULL)
1152
+ { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->rightHash,linker,NULL,listOfJoins->join); }
1153
+ else
1154
+ { hashValue = 0; }
1155
+ }
1156
+
1157
+ /*=======================================================*/
1158
+ /* Add the partial match to the beta memory of the join. */
1159
+ /*=======================================================*/
1160
+
1161
+ if (join->patternIsExists)
1162
+ { UpdateBetaPMLinks(theEnv,linker,existsParent,NULL,listOfJoins->join,hashValue,listOfJoins->enterDirection); }
1163
+ else
1164
+ { UpdateBetaPMLinks(theEnv,linker,NULL,rhsBinds,listOfJoins->join,hashValue,listOfJoins->enterDirection); }
1165
+
1166
+ if (listOfJoins->enterDirection == LHS)
1167
+ { NetworkAssertLeft(theEnv,linker,listOfJoins->join,operation); }
1168
+ else
1169
+ { NetworkAssertRight(theEnv,linker,listOfJoins->join,operation); }
1170
+
1171
+ listOfJoins = listOfJoins->next;
1172
+ }
1173
+ }
1174
+
1175
+ /********************************************************************/
1176
+ /* JoinNetErrorMessage: Prints an informational message indicating */
1177
+ /* which join of a rule generated an error when a join expression */
1178
+ /* was being evaluated. */
1179
+ /********************************************************************/
1180
+ static void JoinNetErrorMessage(
1181
+ Environment *theEnv,
1182
+ struct joinNode *joinPtr)
1183
+ {
1184
+ PrintErrorID(theEnv,"DRIVE",1,true);
1185
+ WriteString(theEnv,STDERR,"This error occurred in the join network.\n");
1186
+ WriteString(theEnv,STDERR," Problem resides in associated join\n"); /* TBD generate test case for join with JFTR */
1187
+ TraceErrorToRule(theEnv,joinPtr," ");
1188
+ WriteString(theEnv,STDERR,"\n");
1189
+ }
1190
+
1191
+ #endif /* DEFRULE_CONSTRUCT */