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,905 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.41 12/04/22 */
5
+ /* */
6
+ /* FACT MATCH MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Implements the algorithm for pattern matching in */
11
+ /* the fact pattern network. */
12
+ /* */
13
+ /* Principal Programmer(s): */
14
+ /* Gary D. Riley */
15
+ /* */
16
+ /* Contributing Programmer(s): */
17
+ /* */
18
+ /* Revision History: */
19
+ /* */
20
+ /* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
21
+ /* */
22
+ /* 6.24: Removed INCREMENTAL_RESET compilation flag. */
23
+ /* */
24
+ /* Renamed BOOLEAN macro type to intBool. */
25
+ /* */
26
+ /* 6.30: Added support for hashed alpha memories. */
27
+ /* */
28
+ /* Fix for DR0880. 2008-01-24 */
29
+ /* */
30
+ /* Added support for hashed comparisons to */
31
+ /* constants. */
32
+ /* */
33
+ /* Removed conditional code for unsupported */
34
+ /* compilers/operating systems (IBM_MCW, */
35
+ /* MAC_MCW, and IBM_TBC). */
36
+ /* */
37
+ /* 6.40: Pragma once and other inclusion changes. */
38
+ /* */
39
+ /* Added support for booleans with <stdbool.h>. */
40
+ /* */
41
+ /* Removed use of void pointers for specific */
42
+ /* data structures. */
43
+ /* */
44
+ /* UDF redesign. */
45
+ /* */
46
+ /* Watch facts for modify command only prints */
47
+ /* changed slots. */
48
+ /* */
49
+ /* 6.41: Used gensnprintf in place of gensprintf and. */
50
+ /* sprintf. */
51
+ /* */
52
+ /*************************************************************/
53
+
54
+ #include <stdio.h>
55
+
56
+ #include "setup.h"
57
+
58
+ #if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT
59
+
60
+ #include "drive.h"
61
+ #include "engine.h"
62
+ #include "envrnmnt.h"
63
+ #include "extnfunc.h"
64
+ #include "factgen.h"
65
+ #include "factrete.h"
66
+ #include "incrrset.h"
67
+ #include "memalloc.h"
68
+ #include "prntutil.h"
69
+ #include "reteutil.h"
70
+ #include "router.h"
71
+ #include "sysdep.h"
72
+ #include "tmpltdef.h"
73
+
74
+ #include "factmch.h"
75
+
76
+ /***************************************/
77
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
78
+ /***************************************/
79
+
80
+ static bool EvaluatePatternExpression(Environment *,struct factPatternNode *,struct expr *);
81
+ static void TraceErrorToJoin(Environment *,struct factPatternNode *,bool);
82
+ static void ProcessFactAlphaMatch(Environment *,Fact *,struct multifieldMarker *,struct factPatternNode *);
83
+ static struct factPatternNode *GetNextFactPatternNode(Environment *,bool,struct factPatternNode *);
84
+ static bool SkipFactPatternNode(Environment *,struct factPatternNode *);
85
+ static void ProcessMultifieldNode(Environment *,
86
+ struct factPatternNode *,
87
+ struct multifieldMarker *,
88
+ struct multifieldMarker *,size_t,size_t);
89
+ static void PatternNetErrorMessage(Environment *,struct factPatternNode *);
90
+
91
+ /*************************************************************************/
92
+ /* FactPatternMatch: Implements the core loop for fact pattern matching. */
93
+ /*************************************************************************/
94
+ void FactPatternMatch(
95
+ Environment *theEnv,
96
+ Fact *theFact,
97
+ struct factPatternNode *patternPtr,
98
+ size_t offset,
99
+ size_t multifieldsProcessed,
100
+ struct multifieldMarker *markers,
101
+ struct multifieldMarker *endMark)
102
+ {
103
+ size_t theSlotField;
104
+ unsigned short offsetSlot;
105
+ UDFValue theResult;
106
+ struct factPatternNode *tempPtr;
107
+
108
+ /*=========================================================*/
109
+ /* If there's nothing left in the pattern network to match */
110
+ /* against, then the current traversal of the pattern */
111
+ /* network needs to back up. */
112
+ /*=========================================================*/
113
+
114
+ if (patternPtr == NULL) return;
115
+
116
+ /*=======================================================*/
117
+ /* The offsetSlot variable indicates the current offset */
118
+ /* within the multifield slot being pattern matched. */
119
+ /* (Recall that a multifield wildcard or variable */
120
+ /* recursively iterates through all possible bindings.) */
121
+ /* Once a new slot starts being pattern matched, the */
122
+ /* offset is reset to zero. */
123
+ /*=======================================================*/
124
+
125
+ offsetSlot = patternPtr->whichSlot;
126
+
127
+ /*================================================*/
128
+ /* Set up some global parameters for use by the */
129
+ /* Rete access functions and general convenience. */
130
+ /*================================================*/
131
+
132
+ FactData(theEnv)->CurrentPatternFact = theFact;
133
+ FactData(theEnv)->CurrentPatternMarks = markers;
134
+
135
+ /*============================================*/
136
+ /* Loop through each node in pattern network. */
137
+ /*============================================*/
138
+
139
+ while (patternPtr != NULL)
140
+ {
141
+ /*=============================================================*/
142
+ /* Determine the position of the field we're going to pattern */
143
+ /* match. If this routine has been entered recursively because */
144
+ /* of multifield wildcards or variables, then add in the */
145
+ /* additional offset caused by the values which match these */
146
+ /* multifields. This offset may be negative (if for example a */
147
+ /* a multifield matched a zero length value). */
148
+ /*=============================================================*/
149
+
150
+ theSlotField = patternPtr->whichField;
151
+ if (offsetSlot == patternPtr->whichSlot)
152
+ { theSlotField = theSlotField + offset - multifieldsProcessed; }
153
+
154
+ /*===================================*/
155
+ /* Determine if we want to skip this */
156
+ /* node during an incremental reset. */
157
+ /*===================================*/
158
+
159
+ if (SkipFactPatternNode(theEnv,patternPtr))
160
+ { patternPtr = GetNextFactPatternNode(theEnv,true,patternPtr); }
161
+
162
+ /*=========================================================*/
163
+ /* If this is a single field pattern node, then determine */
164
+ /* if the constraints for the node have been satisfied for */
165
+ /* the current field in the slot being examined. */
166
+ /*=========================================================*/
167
+
168
+ else if (patternPtr->header.singlefieldNode)
169
+ {
170
+ /*==================================================*/
171
+ /* If we're at the last slot in the pattern, make */
172
+ /* sure the number of fields in the fact correspond */
173
+ /* to the number of fields required by the pattern */
174
+ /* based on the binding of multifield variables. */
175
+ /*==================================================*/
176
+
177
+ bool skipit = false;
178
+ if (patternPtr->header.endSlot &&
179
+ ((FactData(theEnv)->CurrentPatternMarks == NULL) ?
180
+ false :
181
+ (FactData(theEnv)->CurrentPatternMarks->where.whichSlotNumber == patternPtr->whichSlot)) &&
182
+ (FactData(theEnv)->CurrentPatternFact->theProposition.contents
183
+ [patternPtr->whichSlot].header->type == MULTIFIELD_TYPE))
184
+ {
185
+ if ((patternPtr->leaveFields + theSlotField) !=
186
+ FactData(theEnv)->CurrentPatternFact->theProposition.contents
187
+ [patternPtr->whichSlot].multifieldValue->length)
188
+ { skipit = true; }
189
+ }
190
+
191
+ if (skipit)
192
+ { patternPtr = GetNextFactPatternNode(theEnv,true,patternPtr); }
193
+ else
194
+
195
+ if (patternPtr->header.selector)
196
+ {
197
+ if (EvaluatePatternExpression(theEnv,patternPtr,patternPtr->networkTest->nextArg))
198
+ {
199
+ EvaluateExpression(theEnv,patternPtr->networkTest,&theResult);
200
+
201
+ tempPtr = (struct factPatternNode *) FindHashedPatternNode(theEnv,patternPtr,theResult.header->type,theResult.value);
202
+ }
203
+ else
204
+ { tempPtr = NULL; }
205
+
206
+ if (tempPtr != NULL)
207
+ {
208
+ if (SkipFactPatternNode(theEnv,tempPtr))
209
+ { patternPtr = GetNextFactPatternNode(theEnv,true,patternPtr); }
210
+ else
211
+ {
212
+ if (tempPtr->header.stopNode)
213
+ { ProcessFactAlphaMatch(theEnv,theFact,markers,tempPtr); }
214
+
215
+ patternPtr = GetNextFactPatternNode(theEnv,false,tempPtr);
216
+ }
217
+ }
218
+ else
219
+ { patternPtr = GetNextFactPatternNode(theEnv,true,patternPtr); }
220
+ }
221
+
222
+ /*=============================================*/
223
+ /* If the constraints are satisified, then ... */
224
+ /*=============================================*/
225
+
226
+ else if (EvaluatePatternExpression(theEnv,patternPtr,patternPtr->networkTest))
227
+ {
228
+ /*=======================================================*/
229
+ /* If a leaf pattern node has been successfully reached, */
230
+ /* then the pattern has been satisified. Generate an */
231
+ /* alpha match to store in the pattern node. */
232
+ /*=======================================================*/
233
+
234
+ if (patternPtr->header.stopNode)
235
+ { ProcessFactAlphaMatch(theEnv,theFact,markers,patternPtr); }
236
+
237
+ /*===================================*/
238
+ /* Move on to the next pattern node. */
239
+ /*===================================*/
240
+
241
+ patternPtr = GetNextFactPatternNode(theEnv,false,patternPtr);
242
+ }
243
+
244
+ /*==============================================*/
245
+ /* Otherwise, move on to the next pattern node. */
246
+ /*==============================================*/
247
+
248
+ else
249
+ { patternPtr = GetNextFactPatternNode(theEnv,true,patternPtr); }
250
+ }
251
+
252
+ /*======================================================*/
253
+ /* If this is a multifield pattern node, then determine */
254
+ /* if the constraints for the node have been satisfied */
255
+ /* for the current field in the slot being examined. */
256
+ /*======================================================*/
257
+
258
+ else if (patternPtr->header.multifieldNode)
259
+ {
260
+ /*========================================================*/
261
+ /* Determine if the multifield pattern node's constraints */
262
+ /* are satisfied. If we've traversed to a different slot */
263
+ /* than the one we started this routine with, then the */
264
+ /* offset into the slot is reset to zero. */
265
+ /*========================================================*/
266
+
267
+ if (offsetSlot == patternPtr->whichSlot)
268
+ { ProcessMultifieldNode(theEnv,patternPtr,markers,endMark,offset,multifieldsProcessed); }
269
+ else
270
+ { ProcessMultifieldNode(theEnv,patternPtr,markers,endMark,0,0); }
271
+
272
+ /*===================================================*/
273
+ /* Move on to the next pattern node. Since the lower */
274
+ /* branches of the pattern network have already been */
275
+ /* recursively processed by ProcessMultifieldNode, */
276
+ /* we get the next pattern node by treating this */
277
+ /* multifield pattern node as if it were a single */
278
+ /* field pattern node that failed its constraint. */
279
+ /*===================================================*/
280
+
281
+ patternPtr = GetNextFactPatternNode(theEnv,true,patternPtr);
282
+ }
283
+ }
284
+ }
285
+
286
+ /**************************************************************/
287
+ /* ProcessMultifieldNode: Handles recursive pattern matching */
288
+ /* when a multifield wildcard or variable is encountered as */
289
+ /* a slot constraint. The pattern matching routine is called */
290
+ /* iteratively for each possible binding of the multifield */
291
+ /* wildcard or variable. */
292
+ /**************************************************************/
293
+ static void ProcessMultifieldNode(
294
+ Environment *theEnv,
295
+ struct factPatternNode *thePattern,
296
+ struct multifieldMarker *markers,
297
+ struct multifieldMarker *endMark,
298
+ size_t offset,
299
+ size_t multifieldsProcessed)
300
+ {
301
+ struct multifieldMarker *newMark, *oldMark;
302
+ size_t fieldsRemaining;
303
+ size_t i;
304
+ size_t repeatCount;
305
+ Multifield *theSlotValue;
306
+ UDFValue theResult;
307
+ struct factPatternNode *tempPtr;
308
+ bool success;
309
+
310
+ /*========================================*/
311
+ /* Get a pointer to the slot value of the */
312
+ /* multifield slot being pattern matched. */
313
+ /*========================================*/
314
+
315
+ theSlotValue =
316
+ FactData(theEnv)->CurrentPatternFact->theProposition.contents[thePattern->whichSlot].multifieldValue;
317
+
318
+ /*===============================================*/
319
+ /* Save the value of the markers already stored. */
320
+ /*===============================================*/
321
+
322
+ oldMark = markers;
323
+
324
+ /*===========================================*/
325
+ /* Create a new multifield marker and append */
326
+ /* it to the end of the current list. */
327
+ /*===========================================*/
328
+
329
+ newMark = get_struct(theEnv,multifieldMarker);
330
+
331
+ newMark->whichField = thePattern->whichField - 1;
332
+ newMark->where.whichSlotNumber = thePattern->whichSlot;
333
+ newMark->startPosition = (thePattern->whichField - 1) + offset - multifieldsProcessed;
334
+ newMark->next = NULL;
335
+
336
+ if (endMark == NULL)
337
+ {
338
+ markers = newMark;
339
+ FactData(theEnv)->CurrentPatternMarks = markers;
340
+ }
341
+ else
342
+ { endMark->next = newMark; }
343
+
344
+ /*============================================*/
345
+ /* Handle a multifield constraint as the last */
346
+ /* constraint of a slot as a special case. */
347
+ /*============================================*/
348
+
349
+ if (thePattern->header.endSlot)
350
+ {
351
+ if (theSlotValue->length < (newMark->startPosition + thePattern->leaveFields))
352
+ { newMark->range = 0; }
353
+ else
354
+ { newMark->range = theSlotValue->length - (newMark->startPosition + thePattern->leaveFields); }
355
+
356
+ /*===========================================*/
357
+ /* Determine if the constraint is satisfied. */
358
+ /*===========================================*/
359
+
360
+ if (thePattern->header.selector)
361
+ {
362
+ if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg))
363
+ {
364
+ EvaluateExpression(theEnv,thePattern->networkTest,&theResult);
365
+
366
+ thePattern = (struct factPatternNode *) FindHashedPatternNode(theEnv,thePattern,theResult.header->type,theResult.value);
367
+ if (thePattern != NULL)
368
+ { success = true; }
369
+ else
370
+ { success = false; }
371
+ }
372
+ else
373
+ { success = false; }
374
+ }
375
+ else if ((thePattern->networkTest == NULL) ?
376
+ true :
377
+ (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest)))
378
+ { success = true; }
379
+ else
380
+ { success = false; }
381
+
382
+ if (success)
383
+ {
384
+ /*=======================================================*/
385
+ /* If a leaf pattern node has been successfully reached, */
386
+ /* then the pattern has been satisified. Generate an */
387
+ /* alpha match to store in the pattern node. */
388
+ /*=======================================================*/
389
+
390
+ if (thePattern->header.stopNode)
391
+ { ProcessFactAlphaMatch(theEnv,FactData(theEnv)->CurrentPatternFact,FactData(theEnv)->CurrentPatternMarks,thePattern); }
392
+
393
+ /*=============================================*/
394
+ /* Recursively continue pattern matching based */
395
+ /* on the multifield binding just generated. */
396
+ /*=============================================*/
397
+
398
+ FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
399
+ thePattern->nextLevel,0,0,FactData(theEnv)->CurrentPatternMarks,newMark);
400
+ }
401
+
402
+ /*================================================*/
403
+ /* Discard the multifield marker since we've done */
404
+ /* all the pattern matching for this binding of */
405
+ /* the multifield slot constraint. */
406
+ /*================================================*/
407
+
408
+ rtn_struct(theEnv,multifieldMarker,newMark);
409
+ if (endMark != NULL) endMark->next = NULL;
410
+ FactData(theEnv)->CurrentPatternMarks = oldMark;
411
+ return;
412
+ }
413
+
414
+ /*===============================================================*/
415
+ /* Stop matching if there aren't enough values left in the fact. */
416
+ /*===============================================================*/
417
+
418
+ if (theSlotValue->length < (newMark->startPosition + thePattern->leaveFields))
419
+ {
420
+ rtn_struct(theEnv,multifieldMarker,newMark);
421
+ if (endMark != NULL) endMark->next = NULL;
422
+ FactData(theEnv)->CurrentPatternMarks = oldMark;
423
+ return;
424
+ }
425
+
426
+ /*==============================================*/
427
+ /* Perform matching for nodes beneath this one. */
428
+ /*==============================================*/
429
+
430
+ fieldsRemaining = theSlotValue->length - (newMark->startPosition + thePattern->leaveFields);
431
+
432
+ for (i = 0; i <= fieldsRemaining; i++)
433
+ {
434
+ repeatCount = fieldsRemaining - i;
435
+
436
+ newMark->range = repeatCount;
437
+
438
+ if (thePattern->header.selector)
439
+ {
440
+ if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg))
441
+ {
442
+ EvaluateExpression(theEnv,thePattern->networkTest,&theResult);
443
+
444
+ tempPtr = (struct factPatternNode *) FindHashedPatternNode(theEnv,thePattern,theResult.header->type,theResult.value);
445
+ if (tempPtr != NULL)
446
+ {
447
+ FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
448
+ tempPtr->nextLevel,offset + repeatCount,multifieldsProcessed+1,
449
+ FactData(theEnv)->CurrentPatternMarks,newMark);
450
+ }
451
+ }
452
+ }
453
+ else if ((thePattern->networkTest == NULL) ?
454
+ true :
455
+ (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest)))
456
+ {
457
+ FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
458
+ thePattern->nextLevel,offset + repeatCount,multifieldsProcessed+1,
459
+ FactData(theEnv)->CurrentPatternMarks,newMark);
460
+ }
461
+ }
462
+
463
+ /*======================================================*/
464
+ /* Get rid of the marker created for a multifield node. */
465
+ /*======================================================*/
466
+
467
+ rtn_struct(theEnv,multifieldMarker,newMark);
468
+ if (endMark != NULL) endMark->next = NULL;
469
+ FactData(theEnv)->CurrentPatternMarks = oldMark;
470
+ }
471
+
472
+ /******************************************************/
473
+ /* GetNextFactPatternNode: Returns the next node in a */
474
+ /* pattern network tree to be traversed. The next */
475
+ /* node is computed using a depth first traversal. */
476
+ /******************************************************/
477
+ static struct factPatternNode *GetNextFactPatternNode(
478
+ Environment *theEnv,
479
+ bool finishedMatching,
480
+ struct factPatternNode *thePattern)
481
+ {
482
+ EvaluationData(theEnv)->EvaluationError = false;
483
+
484
+ /*===================================================*/
485
+ /* If pattern matching was successful at the current */
486
+ /* node in the tree and it's possible to go deeper */
487
+ /* into the tree, then move down to the next level. */
488
+ /*===================================================*/
489
+
490
+ if (finishedMatching == false)
491
+ { if (thePattern->nextLevel != NULL) return(thePattern->nextLevel); }
492
+
493
+ /*================================================*/
494
+ /* Keep backing up toward the root of the pattern */
495
+ /* network until a side branch can be taken. */
496
+ /*================================================*/
497
+
498
+ while ((thePattern->rightNode == NULL) ||
499
+ ((thePattern->lastLevel != NULL) &&
500
+ (thePattern->lastLevel->header.selector)))
501
+ {
502
+ /*========================================*/
503
+ /* Back up to check the next side branch. */
504
+ /*========================================*/
505
+
506
+ thePattern = thePattern->lastLevel;
507
+
508
+ /*======================================*/
509
+ /* If we branched up from the root, the */
510
+ /* entire tree has been traversed. */
511
+ /*======================================*/
512
+
513
+ if (thePattern == NULL) return NULL;
514
+
515
+ /*======================================*/
516
+ /* Skip selector constants and pop back */
517
+ /* back to the selector node. */
518
+ /*======================================*/
519
+
520
+ if ((thePattern->lastLevel != NULL) &&
521
+ (thePattern->lastLevel->header.selector))
522
+ { thePattern = thePattern->lastLevel; }
523
+
524
+ /*===================================================*/
525
+ /* If we branched up to a multifield node, then stop */
526
+ /* since these nodes are handled recursively. The */
527
+ /* previous call to the pattern matching algorithm */
528
+ /* on the stack will handle backing up to the nodes */
529
+ /* above the multifield node in the pattern network. */
530
+ /*===================================================*/
531
+
532
+ if (thePattern->header.multifieldNode) return NULL;
533
+ }
534
+
535
+ /*==================================*/
536
+ /* Move on to the next side branch. */
537
+ /*==================================*/
538
+
539
+ return(thePattern->rightNode);
540
+ }
541
+
542
+ /*******************************************************/
543
+ /* ProcessFactAlphaMatch: When a fact pattern has been */
544
+ /* satisfied, this routine creates an alpha match to */
545
+ /* store in the pattern network and then sends the */
546
+ /* new alpha match through the join network. */
547
+ /*******************************************************/
548
+ static void ProcessFactAlphaMatch(
549
+ Environment *theEnv,
550
+ Fact *theFact,
551
+ struct multifieldMarker *theMarks,
552
+ struct factPatternNode *thePattern)
553
+ {
554
+ struct partialMatch *theMatch;
555
+ struct patternMatch *listOfMatches;
556
+ struct joinNode *listOfJoins;
557
+ unsigned long hashValue;
558
+
559
+ /*============================================*/
560
+ /* Create the hash value for the alpha match. */
561
+ /*============================================*/
562
+
563
+ hashValue = ComputeRightHashValue(theEnv,&thePattern->header);
564
+
565
+ /*===========================================*/
566
+ /* Create the partial match for the pattern. */
567
+ /*===========================================*/
568
+
569
+ theMatch = CreateAlphaMatch(theEnv,theFact,theMarks,(struct patternNodeHeader *) &thePattern->header,hashValue);
570
+ theMatch->owner = &thePattern->header;
571
+
572
+ /*=======================================================*/
573
+ /* Add the pattern to the list of matches for this fact. */
574
+ /*=======================================================*/
575
+
576
+ listOfMatches = (struct patternMatch *) theFact->list;
577
+ theFact->list = get_struct(theEnv,patternMatch);
578
+ ((struct patternMatch *) theFact->list)->next = listOfMatches;
579
+ ((struct patternMatch *) theFact->list)->matchingPattern = (struct patternNodeHeader *) thePattern;
580
+ ((struct patternMatch *) theFact->list)->theMatch = theMatch;
581
+
582
+ /*================================================================*/
583
+ /* Send the partial match to the joins connected to this pattern. */
584
+ /*================================================================*/
585
+
586
+ for (listOfJoins = thePattern->header.entryJoin;
587
+ listOfJoins != NULL;
588
+ listOfJoins = listOfJoins->rightMatchNode)
589
+ { NetworkAssert(theEnv,theMatch,listOfJoins); }
590
+ }
591
+
592
+ /*****************************************************************/
593
+ /* EvaluatePatternExpression: Performs a faster evaluation for */
594
+ /* fact pattern network expressions than if EvaluateExpression */
595
+ /* were used directly. */
596
+ /*****************************************************************/
597
+ static bool EvaluatePatternExpression(
598
+ Environment *theEnv,
599
+ struct factPatternNode *patternPtr,
600
+ struct expr *theTest)
601
+ {
602
+ UDFValue theResult;
603
+ struct expr *oldArgument;
604
+ bool rv;
605
+
606
+ /*=====================================*/
607
+ /* A pattern node without a constraint */
608
+ /* is always satisfied. */
609
+ /*=====================================*/
610
+
611
+ if (theTest == NULL) return true;
612
+
613
+ /*======================================*/
614
+ /* Evaluate pattern network primitives. */
615
+ /*======================================*/
616
+
617
+ switch(theTest->type)
618
+ {
619
+ /*==============================================*/
620
+ /* This primitive compares the value stored in */
621
+ /* a single field slot to a constant for either */
622
+ /* equality or inequality. */
623
+ /*==============================================*/
624
+
625
+ case FACT_PN_CONSTANT1:
626
+ oldArgument = EvaluationData(theEnv)->CurrentExpression;
627
+ EvaluationData(theEnv)->CurrentExpression = theTest;
628
+ rv = FactPNConstant1(theEnv,theTest->value,&theResult);
629
+ EvaluationData(theEnv)->CurrentExpression = oldArgument;
630
+ return(rv);
631
+
632
+ /*=============================================*/
633
+ /* This primitive compares the value stored in */
634
+ /* a multifield slot to a constant for either */
635
+ /* equality or inequality. */
636
+ /*=============================================*/
637
+
638
+ case FACT_PN_CONSTANT2:
639
+ oldArgument = EvaluationData(theEnv)->CurrentExpression;
640
+ EvaluationData(theEnv)->CurrentExpression = theTest;
641
+ rv = FactPNConstant2(theEnv,theTest->value,&theResult);
642
+ EvaluationData(theEnv)->CurrentExpression = oldArgument;
643
+ return(rv);
644
+
645
+ /*================================================*/
646
+ /* This primitive determines if a multifield slot */
647
+ /* contains at least a certain number of fields. */
648
+ /*================================================*/
649
+
650
+ case FACT_SLOT_LENGTH:
651
+ oldArgument = EvaluationData(theEnv)->CurrentExpression;
652
+ EvaluationData(theEnv)->CurrentExpression = theTest;
653
+ rv = FactSlotLength(theEnv,theTest->value,&theResult);
654
+ EvaluationData(theEnv)->CurrentExpression = oldArgument;
655
+ return(rv);
656
+ }
657
+
658
+ /*==============================================*/
659
+ /* Evaluate "or" expressions by evaluating each */
660
+ /* argument and return true if any of them */
661
+ /* evaluated to true, otherwise return false. */
662
+ /*==============================================*/
663
+
664
+ if (theTest->value == ExpressionData(theEnv)->PTR_OR)
665
+ {
666
+ for (theTest = theTest->argList;
667
+ theTest != NULL;
668
+ theTest = theTest->nextArg)
669
+ {
670
+ if (EvaluatePatternExpression(theEnv,patternPtr,theTest) == true)
671
+ {
672
+ if (EvaluationData(theEnv)->EvaluationError) return false;
673
+ return true;
674
+ }
675
+ if (EvaluationData(theEnv)->EvaluationError) return false;
676
+ }
677
+
678
+ return false;
679
+ }
680
+
681
+ /*===============================================*/
682
+ /* Evaluate "and" expressions by evaluating each */
683
+ /* argument and return false if any of them */
684
+ /* evaluated to false, otherwise return true. */
685
+ /*===============================================*/
686
+
687
+ else if (theTest->value == ExpressionData(theEnv)->PTR_AND)
688
+ {
689
+ for (theTest = theTest->argList;
690
+ theTest != NULL;
691
+ theTest = theTest->nextArg)
692
+ {
693
+ if (EvaluatePatternExpression(theEnv,patternPtr,theTest) == false)
694
+ { return false; }
695
+ if (EvaluationData(theEnv)->EvaluationError) return false;
696
+ }
697
+
698
+ return true;
699
+ }
700
+
701
+ /*==========================================================*/
702
+ /* Evaluate all other expressions using EvaluateExpression. */
703
+ /*==========================================================*/
704
+
705
+ if (EvaluateExpression(theEnv,theTest,&theResult))
706
+ {
707
+ PatternNetErrorMessage(theEnv,patternPtr);
708
+ return false;
709
+ }
710
+
711
+ if (theResult.value == FalseSymbol(theEnv))
712
+ { return false; }
713
+
714
+ return true;
715
+ }
716
+
717
+ /************************************************************************/
718
+ /* PatternNetErrorMessage: Prints the informational header to the error */
719
+ /* message that occurs when a error occurs as the result of */
720
+ /* evaluating an expression in the fact pattern network. Prints the */
721
+ /* fact currently being pattern matched and the field number or slot */
722
+ /* name in the pattern from which the error originated. The error is */
723
+ /* then trace to the point where the pattern enters the join network */
724
+ /* so that the names of the rule which utilize the pattern can also */
725
+ /* be printed. */
726
+ /************************************************************************/
727
+ static void PatternNetErrorMessage(
728
+ Environment *theEnv,
729
+ struct factPatternNode *patternPtr)
730
+ {
731
+ char buffer[60];
732
+ struct templateSlot *theSlots;
733
+ unsigned short i;
734
+
735
+ /*=======================================*/
736
+ /* Print the fact being pattern matched. */
737
+ /*=======================================*/
738
+
739
+ PrintErrorID(theEnv,"FACTMCH",1,true);
740
+ WriteString(theEnv,STDERR,"This error occurred in the fact pattern network.\n");
741
+ WriteString(theEnv,STDERR," Currently active fact: ");
742
+ PrintFact(theEnv,STDERR,FactData(theEnv)->CurrentPatternFact,false,false,NULL);
743
+ WriteString(theEnv,STDERR,"\n");
744
+
745
+ /*==============================================*/
746
+ /* Print the field position or slot name of the */
747
+ /* pattern from which the error originated. */
748
+ /*==============================================*/
749
+
750
+ if (FactData(theEnv)->CurrentPatternFact->whichDeftemplate->implied)
751
+ { gensnprintf(buffer,sizeof(buffer)," Problem resides in field #%d\n",patternPtr->whichField); }
752
+ else
753
+ {
754
+ theSlots = FactData(theEnv)->CurrentPatternFact->whichDeftemplate->slotList;
755
+ for (i = 0; i < patternPtr->whichSlot; i++) theSlots = theSlots->next;
756
+ gensnprintf(buffer,sizeof(buffer)," Problem resides in slot %s\n",theSlots->slotName->contents);
757
+ }
758
+
759
+ WriteString(theEnv,STDERR,buffer);
760
+
761
+ /*==========================================================*/
762
+ /* Trace the pattern to its entry point to the join network */
763
+ /* (which then traces to the defrule data structure so that */
764
+ /* the name(s) of the rule(s) utilizing the patterns can be */
765
+ /* printed). */
766
+ /*==========================================================*/
767
+
768
+ TraceErrorToJoin(theEnv,patternPtr,false);
769
+ WriteString(theEnv,STDERR,"\n");
770
+ }
771
+
772
+ /***************************************************************************/
773
+ /* TraceErrorToJoin: Traces the cause of an evaluation error which occured */
774
+ /* in the fact pattern network to the entry join in the join network for */
775
+ /* the pattern from which the error originated. Once the entry join is */
776
+ /* reached, the error is then traced to the defrule data structures so */
777
+ /* that the name of the rule(s) containing the pattern can be printed. */
778
+ /***************************************************************************/
779
+ static void TraceErrorToJoin(
780
+ Environment *theEnv,
781
+ struct factPatternNode *patternPtr,
782
+ bool traceRight)
783
+ {
784
+ struct joinNode *joinPtr;
785
+
786
+ while (patternPtr != NULL)
787
+ {
788
+ if (patternPtr->header.stopNode)
789
+ {
790
+ for (joinPtr = patternPtr->header.entryJoin;
791
+ joinPtr != NULL;
792
+ joinPtr = joinPtr->rightMatchNode)
793
+ { TraceErrorToRule(theEnv,joinPtr," "); }
794
+ }
795
+ else
796
+ { TraceErrorToJoin(theEnv,patternPtr->nextLevel,true); }
797
+
798
+ if (traceRight) patternPtr = patternPtr->rightNode;
799
+ else patternPtr = NULL;
800
+ }
801
+ }
802
+
803
+ /***********************************************************************/
804
+ /* SkipFactPatternNode: During an incremental reset, only fact pattern */
805
+ /* nodes associated with new patterns are traversed. Given a pattern */
806
+ /* node, this routine will return true if the pattern node should be */
807
+ /* traversed during incremental reset pattern matching or false if */
808
+ /* the node should be skipped. */
809
+ /***********************************************************************/
810
+ static bool SkipFactPatternNode(
811
+ Environment *theEnv,
812
+ struct factPatternNode *thePattern)
813
+ {
814
+ #if (! RUN_TIME) && (! BLOAD_ONLY)
815
+ if (EngineData(theEnv)->IncrementalResetInProgress &&
816
+ (thePattern->header.initialize == false))
817
+ { return true; }
818
+ #endif
819
+
820
+ return false;
821
+ }
822
+
823
+ /***************************************************************/
824
+ /* MarkFactPatternForIncrementalReset: Sets the initialization */
825
+ /* field of a fact pattern for use with incremental reset. */
826
+ /* This is called before an incremental reset for newly added */
827
+ /* patterns to indicate that the pattern nodes should be */
828
+ /* traversed and then after an incremental reset to indicate */
829
+ /* that the nodes were traversed ("initialized") by the */
830
+ /* incremental reset. */
831
+ /***************************************************************/
832
+ void MarkFactPatternForIncrementalReset(
833
+ Environment *theEnv,
834
+ struct patternNodeHeader *thePattern,
835
+ bool value)
836
+ {
837
+ struct factPatternNode *patternPtr = (struct factPatternNode *) thePattern;
838
+ struct joinNode *theJoin;
839
+ #if MAC_XCD
840
+ #pragma unused(theEnv)
841
+ #endif
842
+
843
+ /*=====================================*/
844
+ /* We should be passed a valid pointer */
845
+ /* to a fact pattern network node. */
846
+ /*=====================================*/
847
+
848
+ Bogus(patternPtr == NULL);
849
+
850
+ /*===============================================================*/
851
+ /* If the pattern was previously initialized, then don't bother */
852
+ /* with it unless the pattern was subsumed by another pattern */
853
+ /* and associated with a join that hasn't been initialized. */
854
+ /* DR0880 2008-01-24 */
855
+ /*===============================================================*/
856
+
857
+ if (patternPtr->header.initialize == false)
858
+ {
859
+ for (theJoin = patternPtr->header.entryJoin;
860
+ theJoin != NULL;
861
+ theJoin = theJoin->rightMatchNode)
862
+ {
863
+ if (theJoin->initialize == false)
864
+ { return; }
865
+ }
866
+ }
867
+
868
+ /*======================================================*/
869
+ /* Set the initialization field of this pattern network */
870
+ /* node and all pattern network nodes which preceed it. */
871
+ /*======================================================*/
872
+
873
+ while (patternPtr != NULL)
874
+ {
875
+ patternPtr->header.initialize = value;
876
+ patternPtr = patternPtr->lastLevel;
877
+ }
878
+ }
879
+
880
+ /**************************************************************/
881
+ /* FactsIncrementalReset: Incremental reset function for the */
882
+ /* fact pattern network. Asserts all facts in the fact-list */
883
+ /* so that they repeat the pattern matching process. During */
884
+ /* an incremental reset, newly added patterns should be the */
885
+ /* only active patterns in the fact pattern network. */
886
+ /**************************************************************/
887
+ void FactsIncrementalReset(
888
+ Environment *theEnv)
889
+ {
890
+ Fact *factPtr;
891
+
892
+ for (factPtr = GetNextFact(theEnv,NULL);
893
+ factPtr != NULL;
894
+ factPtr = GetNextFact(theEnv,factPtr))
895
+ {
896
+ EngineData(theEnv)->JoinOperationInProgress = true;
897
+ FactPatternMatch(theEnv,factPtr,
898
+ factPtr->whichDeftemplate->patternNetwork,
899
+ 0,0,NULL,NULL);
900
+ EngineData(theEnv)->JoinOperationInProgress = false;
901
+ }
902
+ }
903
+
904
+ #endif /* DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT */
905
+