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,2082 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 06/22/18 */
5
+ /* */
6
+ /* REORDER MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Provides routines necessary for converting the */
11
+ /* the LHS of a rule into an appropriate form suitable for */
12
+ /* the KB Rete topology. This includes transforming the */
13
+ /* LHS so there is at most one "or" CE (and this is the */
14
+ /* first CE of the LHS if it is used), adding initial */
15
+ /* patterns to the LHS (if no LHS is specified or a "test" */
16
+ /* or "not" CE is the first pattern within an "and" CE), */
17
+ /* removing redundant CEs, and determining appropriate */
18
+ /* information on nesting for implementing joins from the */
19
+ /* right. */
20
+ /* */
21
+ /* Principal Programmer(s): */
22
+ /* Gary D. Riley */
23
+ /* */
24
+ /* Contributing Programmer(s): */
25
+ /* */
26
+ /* Revision History: */
27
+ /* */
28
+ /* 6.30: Support for join network changes. */
29
+ /* */
30
+ /* Changes to the algorithm for processing */
31
+ /* not/and CE groups. */
32
+ /* */
33
+ /* Additional optimizations for combining */
34
+ /* conditional elements. */
35
+ /* */
36
+ /* Added support for hashed alpha memories. */
37
+ /* */
38
+ /* 6.31: Fixed crash bug that occurred from */
39
+ /* AssignPatternIndices incorrectly */
40
+ /* assigning the wrong join depth to */
41
+ /* multiply nested nand groups. */
42
+ /* */
43
+ /* Removed the marked flag used for not/and */
44
+ /* unification. */
45
+ /* */
46
+ /* Fix for incorrect join depth computed by */
47
+ /* AssignPatternIndices for not/and groups. */
48
+ /* */
49
+ /* 6.40: Pragma once and other inclusion changes. */
50
+ /* */
51
+ /* Added support for booleans with <stdbool.h>. */
52
+ /* */
53
+ /* Removed use of void pointers for specific */
54
+ /* data structures. */
55
+ /* */
56
+ /* Removed initial-fact support. */
57
+ /* */
58
+ /*************************************************************/
59
+
60
+ #include "setup.h"
61
+
62
+ #if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
63
+
64
+ #include <stdio.h>
65
+
66
+ #include "cstrnutl.h"
67
+ #include "envrnmnt.h"
68
+ #include "extnfunc.h"
69
+ #include "memalloc.h"
70
+ #include "pattern.h"
71
+ #include "prntutil.h"
72
+ #include "router.h"
73
+ #include "rulelhs.h"
74
+
75
+ #if DEVELOPER && DEBUGGING_FUNCTIONS
76
+ #include "watch.h"
77
+ #include "rulepsr.h"
78
+ #endif
79
+
80
+ #include "reorder.h"
81
+
82
+ struct variableReference
83
+ {
84
+ CLIPSLexeme *name;
85
+ int depth;
86
+ struct variableReference *next;
87
+ };
88
+
89
+ struct groupReference
90
+ {
91
+ struct lhsParseNode *theGroup;
92
+ int depth;
93
+ struct groupReference *next;
94
+ };
95
+
96
+ /***************************************/
97
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
98
+ /***************************************/
99
+
100
+ static struct lhsParseNode *ReverseAndOr(Environment *,struct lhsParseNode *,struct lhsParseNode *,int);
101
+ static struct lhsParseNode *PerformReorder1(Environment *,struct lhsParseNode *,bool *,int);
102
+ static struct lhsParseNode *PerformReorder2(Environment *,struct lhsParseNode *,bool *,int);
103
+ static struct lhsParseNode *CompressCEs(Environment *,struct lhsParseNode *,bool *,int);
104
+ static void IncrementNandDepth(Environment *,struct lhsParseNode *,bool);
105
+ static struct lhsParseNode *CreateInitialPattern(Environment *);
106
+ static struct lhsParseNode *ReorderDriver(Environment *,struct lhsParseNode *,bool *,int,int);
107
+ static struct lhsParseNode *AddRemainingInitialPatterns(Environment *,struct lhsParseNode *);
108
+ static struct lhsParseNode *AssignPatternIndices(struct lhsParseNode *,short,int,unsigned short);
109
+ static void PropagateIndexSlotPatternValues(struct lhsParseNode *,short,unsigned short,
110
+ CLIPSLexeme *,unsigned short);
111
+ static void PropagateJoinDepth(struct lhsParseNode *,unsigned short);
112
+ static void PropagateNandDepth(struct lhsParseNode *,int,int);
113
+ static void MarkExistsNands(struct lhsParseNode *);
114
+ static unsigned short PropagateWhichCE(struct lhsParseNode *,unsigned short);
115
+ /*
116
+ static void PrintNodes(void *,const char *,struct lhsParseNode *);
117
+ */
118
+
119
+ /********************************************/
120
+ /* ReorderPatterns: Reorders a group of CEs */
121
+ /* to accommodate KB Rete topology. */
122
+ /********************************************/
123
+ struct lhsParseNode *ReorderPatterns(
124
+ Environment *theEnv,
125
+ struct lhsParseNode *theLHS,
126
+ bool *anyChange)
127
+ {
128
+ struct lhsParseNode *newLHS, *tempLHS, *lastLHS;
129
+
130
+ /*=============================================*/
131
+ /* If the LHS of the rule was left unspecified */
132
+ /* (e.g., (defrule x => ...)), then nothing */
133
+ /* more needs to be done. */
134
+ /*=============================================*/
135
+
136
+ if (theLHS == NULL) return(theLHS);
137
+
138
+ /*===========================================================*/
139
+ /* The LHS of a rule is enclosed within an implied "and" CE. */
140
+ /*===========================================================*/
141
+
142
+ newLHS = GetLHSParseNode(theEnv);
143
+ newLHS->pnType = AND_CE_NODE;
144
+ newLHS->right = theLHS;
145
+
146
+ /*==============================================================*/
147
+ /* Mark the nodes to indicate which CE they're associated with. */
148
+ /*==============================================================*/
149
+
150
+ PropagateWhichCE(newLHS,0);
151
+
152
+ /*=======================================================*/
153
+ /* Reorder the patterns to support the KB Rete topology. */
154
+ /*=======================================================*/
155
+
156
+ newLHS = ReorderDriver(theEnv,newLHS,anyChange,1,1);
157
+ newLHS = ReorderDriver(theEnv,newLHS,anyChange,2,1);
158
+
159
+ /*===========================================*/
160
+ /* The top level and CE may have disappeared */
161
+ /* as a result of pattern compression. */
162
+ /*===========================================*/
163
+
164
+ if (newLHS->pnType == OR_CE_NODE)
165
+ {
166
+ for (tempLHS = newLHS->right, lastLHS = NULL;
167
+ tempLHS != NULL;
168
+ lastLHS = tempLHS, tempLHS = tempLHS->bottom)
169
+ {
170
+ if (tempLHS->pnType != AND_CE_NODE)
171
+ {
172
+ theLHS = GetLHSParseNode(theEnv);
173
+ theLHS->pnType = AND_CE_NODE;
174
+ theLHS->right = tempLHS;
175
+ theLHS->bottom = tempLHS->bottom;
176
+ tempLHS->bottom = NULL;
177
+ if (lastLHS == NULL)
178
+ { newLHS->right = theLHS; }
179
+ else
180
+ { lastLHS->bottom = theLHS; }
181
+ tempLHS = theLHS;
182
+ }
183
+ }
184
+ }
185
+ else if (newLHS->pnType != AND_CE_NODE)
186
+ {
187
+ theLHS = newLHS;
188
+ newLHS = GetLHSParseNode(theEnv);
189
+ newLHS->pnType = AND_CE_NODE;
190
+ newLHS->right = theLHS;
191
+ }
192
+
193
+ /*================================================*/
194
+ /* Mark exist not/and groups within the patterns. */
195
+ /*================================================*/
196
+
197
+ if (newLHS->pnType == OR_CE_NODE)
198
+ {
199
+ for (theLHS = newLHS->right;
200
+ theLHS != NULL;
201
+ theLHS = theLHS->bottom)
202
+ { MarkExistsNands(theLHS->right); }
203
+ }
204
+ else
205
+ { MarkExistsNands(newLHS->right); }
206
+
207
+ /*=====================================================*/
208
+ /* Add initial patterns where needed (such as before a */
209
+ /* "test" CE or "not" CE which is the first CE within */
210
+ /* an "and" CE). */
211
+ /*=====================================================*/
212
+
213
+ AddInitialPatterns(theEnv,newLHS);
214
+
215
+ /*===========================================================*/
216
+ /* Number the user specified patterns. Patterns added while */
217
+ /* analyzing the rule are not numbered so that there is no */
218
+ /* confusion when an error message refers to a CE. Also */
219
+ /* propagate field and slot values throughout each pattern. */
220
+ /*===========================================================*/
221
+
222
+ if (newLHS->pnType == OR_CE_NODE) theLHS = newLHS->right;
223
+ else theLHS = newLHS;
224
+
225
+ for (;
226
+ theLHS != NULL;
227
+ theLHS = theLHS->bottom)
228
+ { AssignPatternIndices(theLHS->right,1,1,0); }
229
+
230
+ /*===========================*/
231
+ /* Return the processed LHS. */
232
+ /*===========================*/
233
+
234
+ return(newLHS);
235
+ }
236
+
237
+ /******************************************/
238
+ /* ReorderDriver: Reorders a group of CEs */
239
+ /* to accommodate KB Rete topology. */
240
+ /******************************************/
241
+ static struct lhsParseNode *ReorderDriver(
242
+ Environment *theEnv,
243
+ struct lhsParseNode *theLHS,
244
+ bool *anyChange,
245
+ int pass,
246
+ int depth)
247
+ {
248
+ struct lhsParseNode *argPtr;
249
+ struct lhsParseNode *before, *save;
250
+ bool change, newChange;
251
+ *anyChange = false;
252
+
253
+ /*===================================*/
254
+ /* Continue processing the LHS until */
255
+ /* no more changes have been made. */
256
+ /*===================================*/
257
+
258
+ change = true;
259
+ while (change)
260
+ {
261
+ /*==================================*/
262
+ /* No change yet on this iteration. */
263
+ /*==================================*/
264
+
265
+ change = false;
266
+
267
+ /*=======================================*/
268
+ /* Reorder the current level of the LHS. */
269
+ /*=======================================*/
270
+
271
+ if ((theLHS->pnType == AND_CE_NODE) ||
272
+ (theLHS->pnType == NOT_CE_NODE) ||
273
+ (theLHS->pnType == OR_CE_NODE))
274
+ {
275
+ if (pass == 1) theLHS = PerformReorder1(theEnv,theLHS,&newChange,depth);
276
+ else theLHS = PerformReorder2(theEnv,theLHS,&newChange,depth);
277
+
278
+ if (newChange)
279
+ {
280
+ *anyChange = true;
281
+ change = true;
282
+ }
283
+
284
+ theLHS = CompressCEs(theEnv,theLHS,&newChange,depth);
285
+
286
+ if (newChange)
287
+ {
288
+ *anyChange = true;
289
+ change = true;
290
+ }
291
+ }
292
+
293
+ /*=====================================================*/
294
+ /* Recursively reorder CEs at lower levels in the LHS. */
295
+ /*=====================================================*/
296
+
297
+ before = NULL;
298
+ argPtr = theLHS->right;
299
+
300
+ while (argPtr != NULL)
301
+ {
302
+ /*==================================*/
303
+ /* Remember the next CE to reorder. */
304
+ /*==================================*/
305
+
306
+ save = argPtr->bottom;
307
+
308
+ /*============================================*/
309
+ /* Reorder the current CE at the lower level. */
310
+ /*============================================*/
311
+
312
+ if ((argPtr->pnType == AND_CE_NODE) ||
313
+ (argPtr->pnType == NOT_CE_NODE) ||
314
+ (argPtr->pnType == OR_CE_NODE))
315
+ {
316
+ if (before == NULL)
317
+ {
318
+ argPtr->bottom = NULL;
319
+ theLHS->right = ReorderDriver(theEnv,argPtr,&newChange,pass,depth+1);
320
+ theLHS->right->bottom = save;
321
+ before = theLHS->right;
322
+ }
323
+ else
324
+ {
325
+ argPtr->bottom = NULL;
326
+ before->bottom = ReorderDriver(theEnv,argPtr,&newChange,pass,depth+1);
327
+ before->bottom->bottom = save;
328
+ before = before->bottom;
329
+ }
330
+
331
+ if (newChange)
332
+ {
333
+ *anyChange = true;
334
+ change = true;
335
+ }
336
+ }
337
+ else
338
+ { before = argPtr; }
339
+
340
+ /*====================================*/
341
+ /* Move on to the next CE to reorder. */
342
+ /*====================================*/
343
+
344
+ argPtr = save;
345
+ }
346
+ }
347
+
348
+ /*===========================*/
349
+ /* Return the reordered LHS. */
350
+ /*===========================*/
351
+
352
+ return(theLHS);
353
+ }
354
+
355
+ /********************/
356
+ /* MarkExistsNands: */
357
+ /********************/
358
+ static void MarkExistsNands(
359
+ struct lhsParseNode *theLHS)
360
+ {
361
+ int currentDepth = 1;
362
+ struct lhsParseNode *tmpLHS;
363
+
364
+ while (theLHS != NULL)
365
+ {
366
+ if (IsExistsSubjoin(theLHS,currentDepth))
367
+ {
368
+ theLHS->existsNand = true;
369
+
370
+ for (tmpLHS = theLHS;
371
+ tmpLHS != NULL;
372
+ tmpLHS = tmpLHS->bottom)
373
+ {
374
+ tmpLHS->beginNandDepth--;
375
+ if (tmpLHS->endNandDepth <= currentDepth)
376
+ { break; }
377
+ else
378
+ { tmpLHS->endNandDepth--; }
379
+ }
380
+ }
381
+
382
+ currentDepth = theLHS->endNandDepth;
383
+ theLHS = theLHS->bottom;
384
+ }
385
+ }
386
+
387
+ /****************************************************************/
388
+ /* AddInitialPatterns: Add initial patterns to CEs where needed */
389
+ /* (such as before a "test" CE or "not" CE which is the first */
390
+ /* CE within an "and" CE). */
391
+ /****************************************************************/
392
+ void AddInitialPatterns(
393
+ Environment *theEnv,
394
+ struct lhsParseNode *theLHS)
395
+ {
396
+ struct lhsParseNode *thePattern;
397
+
398
+ /*====================================================*/
399
+ /* If there are multiple disjuncts for the rule, then */
400
+ /* add initial patterns to each disjunct separately. */
401
+ /*====================================================*/
402
+
403
+ if (theLHS->pnType == OR_CE_NODE)
404
+ {
405
+ for (thePattern = theLHS->right;
406
+ thePattern != NULL;
407
+ thePattern = thePattern->bottom)
408
+ { AddInitialPatterns(theEnv,thePattern); }
409
+
410
+ return;
411
+ }
412
+
413
+ /*================================*/
414
+ /* Handle the remaining patterns. */
415
+ /*================================*/
416
+
417
+ theLHS->right = AddRemainingInitialPatterns(theEnv,theLHS->right);
418
+ }
419
+
420
+ /***********************************************************/
421
+ /* PerformReorder1: Reorders a group of CEs to accommodate */
422
+ /* KB Rete topology. The first pass of this function */
423
+ /* transforms or CEs into equivalent forms. */
424
+ /***********************************************************/
425
+ static struct lhsParseNode *PerformReorder1(
426
+ Environment *theEnv,
427
+ struct lhsParseNode *theLHS,
428
+ bool *newChange,
429
+ int depth)
430
+ {
431
+ struct lhsParseNode *argPtr, *lastArg, *nextArg;
432
+ struct lhsParseNode *tempArg, *newNode;
433
+ int count;
434
+ bool change;
435
+
436
+ /*======================================================*/
437
+ /* Loop through the CEs as long as changes can be made. */
438
+ /*======================================================*/
439
+
440
+ change = true;
441
+ *newChange = false;
442
+
443
+ while (change)
444
+ {
445
+ change = false;
446
+ count = 1;
447
+ lastArg = NULL;
448
+
449
+ for (argPtr = theLHS->right;
450
+ argPtr != NULL;)
451
+ {
452
+ /*=============================================================*/
453
+ /* Convert and/or CE combinations into or/and CE combinations. */
454
+ /*=============================================================*/
455
+
456
+ if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == OR_CE_NODE))
457
+ {
458
+ theLHS = ReverseAndOr(theEnv,theLHS,argPtr->right,count);
459
+
460
+ change = true;
461
+ *newChange = true;
462
+ break;
463
+ }
464
+
465
+ /*==============================================================*/
466
+ /* Convert not/or CE combinations into and/not CE combinations. */
467
+ /*==============================================================*/
468
+
469
+ else if ((theLHS->pnType == NOT_CE_NODE) && (argPtr->pnType == OR_CE_NODE))
470
+ {
471
+ change = true;
472
+ *newChange = true;
473
+
474
+ tempArg = argPtr->right;
475
+
476
+ argPtr->right = NULL;
477
+ argPtr->bottom = NULL;
478
+ ReturnLHSParseNodes(theEnv,argPtr);
479
+ theLHS->pnType = AND_CE_NODE;
480
+ theLHS->right = tempArg;
481
+
482
+ while (tempArg != NULL)
483
+ {
484
+ newNode = GetLHSParseNode(theEnv);
485
+ CopyLHSParseNode(theEnv,newNode,tempArg,false);
486
+ newNode->right = tempArg->right;
487
+ newNode->bottom = NULL;
488
+
489
+ tempArg->pnType = NOT_CE_NODE;
490
+ tempArg->negated = false;
491
+ tempArg->exists = false;
492
+ tempArg->existsNand = false;
493
+ tempArg->logical = false;
494
+ tempArg->value = NULL;
495
+ tempArg->expression = NULL;
496
+ tempArg->secondaryExpression = NULL;
497
+ tempArg->right = newNode;
498
+
499
+ tempArg = tempArg->bottom;
500
+ }
501
+
502
+ break;
503
+ }
504
+
505
+ /*=====================================*/
506
+ /* Remove duplication of or CEs within */
507
+ /* or CEs and and CEs within and CEs. */
508
+ /*=====================================*/
509
+
510
+ else if (((theLHS->pnType == OR_CE_NODE) && (argPtr->pnType == OR_CE_NODE)) ||
511
+ ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == AND_CE_NODE)))
512
+ {
513
+ if (argPtr->logical) theLHS->logical = true;
514
+
515
+ change = true;
516
+ *newChange = true;
517
+ tempArg = argPtr->right;
518
+ nextArg = argPtr->bottom;
519
+ argPtr->right = NULL;
520
+ argPtr->bottom = NULL;
521
+ ReturnLHSParseNodes(theEnv,argPtr);
522
+
523
+ if (lastArg == NULL)
524
+ { theLHS->right = tempArg; }
525
+ else
526
+ { lastArg->bottom = tempArg; }
527
+
528
+ argPtr = tempArg;
529
+ while (tempArg->bottom != NULL) tempArg = tempArg->bottom;
530
+ tempArg->bottom = nextArg;
531
+ }
532
+
533
+ /*===================================================*/
534
+ /* If no changes are needed, move on to the next CE. */
535
+ /*===================================================*/
536
+
537
+ else
538
+ {
539
+ count++;
540
+ lastArg = argPtr;
541
+ argPtr = argPtr->bottom;
542
+ }
543
+ }
544
+ }
545
+
546
+ /*===========================*/
547
+ /* Return the reordered LHS. */
548
+ /*===========================*/
549
+
550
+ return(theLHS);
551
+ }
552
+
553
+ /***********************************************************/
554
+ /* PerformReorder2: Reorders a group of CEs to accommodate */
555
+ /* KB Rete topology. The second pass performs all other */
556
+ /* transformations not associated with the or CE. */
557
+ /***********************************************************/
558
+ static struct lhsParseNode *PerformReorder2(
559
+ Environment *theEnv,
560
+ struct lhsParseNode *theLHS,
561
+ bool *newChange,
562
+ int depth)
563
+ {
564
+ struct lhsParseNode *argPtr;
565
+ bool change;
566
+
567
+ /*======================================================*/
568
+ /* Loop through the CEs as long as changes can be made. */
569
+ /*======================================================*/
570
+
571
+ change = true;
572
+ *newChange = false;
573
+
574
+ while (change)
575
+ {
576
+ change = false;
577
+
578
+ for (argPtr = theLHS->right;
579
+ argPtr != NULL;)
580
+ {
581
+ /*=======================================================*/
582
+ /* A sequence of three not CEs grouped within each other */
583
+ /* can be replaced with a single not CE. For example, */
584
+ /* (not (not (not (a)))) can be replaced with (not (a)). */
585
+ /*=======================================================*/
586
+
587
+ if ((theLHS->pnType == NOT_CE_NODE) &&
588
+ (argPtr->pnType == NOT_CE_NODE) &&
589
+ (argPtr->right != NULL) &&
590
+ (argPtr->right->pnType == NOT_CE_NODE))
591
+ {
592
+ change = true;
593
+ *newChange = true;
594
+
595
+ theLHS->right = argPtr->right->right;
596
+
597
+ argPtr->right->right = NULL;
598
+ ReturnLHSParseNodes(theEnv,argPtr);
599
+
600
+ break;
601
+ }
602
+
603
+ /*==========================================*/
604
+ /* Replace two not CEs containing a pattern */
605
+ /* CE with an exists pattern CE. */
606
+ /*==========================================*/
607
+
608
+ else if ((theLHS->pnType == NOT_CE_NODE) &&
609
+ (argPtr->pnType == NOT_CE_NODE) &&
610
+ (argPtr->right != NULL) &&
611
+ (argPtr->right->pnType == PATTERN_CE_NODE))
612
+ {
613
+ change = true;
614
+ *newChange = true;
615
+
616
+ CopyLHSParseNode(theEnv,theLHS,argPtr->right,false);
617
+
618
+ theLHS->negated = true;
619
+ theLHS->exists = true;
620
+ theLHS->existsNand = false;
621
+ theLHS->right = argPtr->right->right;
622
+
623
+ argPtr->right->networkTest = NULL;
624
+ argPtr->right->externalNetworkTest = NULL;
625
+ argPtr->right->secondaryNetworkTest = NULL;
626
+ argPtr->right->externalRightHash = NULL;
627
+ argPtr->right->externalLeftHash = NULL;
628
+ argPtr->right->leftHash = NULL;
629
+ argPtr->right->rightHash = NULL;
630
+ argPtr->right->betaHash = NULL;
631
+ argPtr->right->expression = NULL;
632
+ argPtr->right->secondaryExpression = NULL;
633
+ argPtr->right->userData = NULL;
634
+ argPtr->right->right = NULL;
635
+ argPtr->right->bottom = NULL;
636
+ ReturnLHSParseNodes(theEnv,argPtr);
637
+ break;
638
+ }
639
+
640
+ /*======================================*/
641
+ /* Replace not CEs containing a pattern */
642
+ /* CE with a negated pattern CE. */
643
+ /*======================================*/
644
+
645
+ else if ((theLHS->pnType == NOT_CE_NODE) && (argPtr->pnType == PATTERN_CE_NODE))
646
+ {
647
+ change = true;
648
+ *newChange = true;
649
+
650
+ CopyLHSParseNode(theEnv,theLHS,argPtr,false);
651
+
652
+ theLHS->negated = true;
653
+ theLHS->exists = false;
654
+ theLHS->existsNand = false;
655
+ theLHS->right = argPtr->right;
656
+
657
+ argPtr->networkTest = NULL;
658
+ argPtr->externalNetworkTest = NULL;
659
+ argPtr->secondaryNetworkTest = NULL;
660
+ argPtr->externalRightHash = NULL;
661
+ argPtr->externalLeftHash = NULL;
662
+ argPtr->constantSelector = NULL;
663
+ argPtr->constantValue = NULL;
664
+ argPtr->leftHash = NULL;
665
+ argPtr->rightHash = NULL;
666
+ argPtr->betaHash = NULL;
667
+ argPtr->expression = NULL;
668
+ argPtr->secondaryExpression = NULL;
669
+ argPtr->userData = NULL;
670
+ argPtr->right = NULL;
671
+ argPtr->bottom = NULL;
672
+ ReturnLHSParseNodes(theEnv,argPtr);
673
+ break;
674
+ }
675
+
676
+ /*============================================================*/
677
+ /* Replace "and" and "not" CEs contained within a not CE with */
678
+ /* just the and CE, but increment the nand depths of the */
679
+ /* pattern contained within. */
680
+ /*============================================================*/
681
+
682
+ else if ((theLHS->pnType == NOT_CE_NODE) &&
683
+ ((argPtr->pnType == AND_CE_NODE) || (argPtr->pnType == NOT_CE_NODE)))
684
+ {
685
+ change = true;
686
+ *newChange = true;
687
+
688
+ theLHS->pnType = argPtr->pnType;
689
+
690
+ theLHS->negated = argPtr->negated;
691
+ theLHS->exists = argPtr->exists;
692
+ theLHS->existsNand = argPtr->existsNand;
693
+ theLHS->value = argPtr->value;
694
+ theLHS->logical = argPtr->logical;
695
+ theLHS->right = argPtr->right;
696
+ argPtr->right = NULL;
697
+ argPtr->bottom = NULL;
698
+ ReturnLHSParseNodes(theEnv,argPtr);
699
+
700
+ IncrementNandDepth(theEnv,theLHS->right,true);
701
+ break;
702
+ }
703
+
704
+ /*===================================================*/
705
+ /* If no changes are needed, move on to the next CE. */
706
+ /*===================================================*/
707
+
708
+ else
709
+ {
710
+ argPtr = argPtr->bottom;
711
+ }
712
+ }
713
+ }
714
+
715
+ /*===========================*/
716
+ /* Return the reordered LHS. */
717
+ /*===========================*/
718
+
719
+ return(theLHS);
720
+ }
721
+
722
+ /**************************************************/
723
+ /* ReverseAndOr: Switches and/or CEs into */
724
+ /* equivalent or/and CEs. For example: */
725
+ /* */
726
+ /* (and (or a b) (or c d)) */
727
+ /* */
728
+ /* would be converted to */
729
+ /* */
730
+ /* (or (and a (or c d)) (and b (or c d))), */
731
+ /* */
732
+ /* if the "or" CE being expanded was (or a b). */
733
+ /**************************************************/
734
+ static struct lhsParseNode *ReverseAndOr(
735
+ Environment *theEnv,
736
+ struct lhsParseNode *listOfCEs,
737
+ struct lhsParseNode *orCE,
738
+ int orPosition)
739
+ {
740
+ int count;
741
+ struct lhsParseNode *listOfExpandedOrCEs = NULL;
742
+ struct lhsParseNode *lastExpandedOrCE = NULL;
743
+ struct lhsParseNode *copyOfCEs, *replaceCE;
744
+
745
+ /*========================================================*/
746
+ /* Loop through each of the CEs contained within the "or" */
747
+ /* CE that is being expanded into the enclosing "and" CE. */
748
+ /*========================================================*/
749
+
750
+ while (orCE != NULL)
751
+ {
752
+ /*===============================*/
753
+ /* Make a copy of the and/or CE. */
754
+ /*===============================*/
755
+
756
+ copyOfCEs = CopyLHSParseNodes(theEnv,listOfCEs);
757
+
758
+ /*====================================================*/
759
+ /* Get a pointer to the "or" CE being expanded in the */
760
+ /* copy just made based on the position of the "or" */
761
+ /* CE in the original and/or CE (e.g., 1st, 2nd). */
762
+ /*====================================================*/
763
+
764
+ for (count = 1, replaceCE = copyOfCEs->right;
765
+ count != orPosition;
766
+ count++, replaceCE = replaceCE->bottom)
767
+ { /* Do Nothing*/ }
768
+
769
+ /*===================================================*/
770
+ /* Delete the contents of the "or" CE being expanded */
771
+ /* in the copy of the and/or CE. From the example */
772
+ /* above, (and (or a b) (or c d)) would be replaced */
773
+ /* with (and (or) (or c d)). Note that the "or" CE */
774
+ /* is still left as a placeholder. */
775
+ /*===================================================*/
776
+
777
+ ReturnLHSParseNodes(theEnv,replaceCE->right);
778
+
779
+ /*======================================================*/
780
+ /* Copy the current CE being examined in the "or" CE to */
781
+ /* the placeholder left in the and/or CE. From the */
782
+ /* example above, (and (or) (or c d)) would be replaced */
783
+ /* with (and a (or c d)) if the "a" pattern from the */
784
+ /* "or" CE was being examined or (and b (or c d)) if */
785
+ /* the "b" pattern from the "or" CE was being examined. */
786
+ /*======================================================*/
787
+
788
+ CopyLHSParseNode(theEnv,replaceCE,orCE,true);
789
+ replaceCE->right = CopyLHSParseNodes(theEnv,orCE->right);
790
+
791
+ /*====================================*/
792
+ /* Add the newly expanded "and" CE to */
793
+ /* the list of CEs already expanded. */
794
+ /*====================================*/
795
+
796
+ if (lastExpandedOrCE == NULL)
797
+ {
798
+ listOfExpandedOrCEs = copyOfCEs;
799
+ copyOfCEs->bottom = NULL;
800
+ lastExpandedOrCE = copyOfCEs;
801
+ }
802
+ else
803
+ {
804
+ lastExpandedOrCE->bottom = copyOfCEs;
805
+ copyOfCEs->bottom = NULL;
806
+ lastExpandedOrCE = copyOfCEs;
807
+ }
808
+
809
+ /*=======================================================*/
810
+ /* Move on to the next CE in the "or" CE being expanded. */
811
+ /*=======================================================*/
812
+
813
+ orCE = orCE->bottom;
814
+ }
815
+
816
+ /*=====================================================*/
817
+ /* Release the original and/or CE list to free memory. */
818
+ /*=====================================================*/
819
+
820
+ ReturnLHSParseNodes(theEnv,listOfCEs);
821
+
822
+ /*================================================*/
823
+ /* Wrap an or CE around the list of expanded CEs. */
824
+ /*================================================*/
825
+
826
+ copyOfCEs = GetLHSParseNode(theEnv);
827
+ copyOfCEs->pnType = OR_CE_NODE;
828
+ copyOfCEs->right = listOfExpandedOrCEs;
829
+
830
+ /*================================*/
831
+ /* Return the newly expanded CEs. */
832
+ /*================================*/
833
+
834
+ return(copyOfCEs);
835
+ }
836
+
837
+ /****************/
838
+ /* CompressCEs: */
839
+ /****************/
840
+ static struct lhsParseNode *CompressCEs(
841
+ Environment *theEnv,
842
+ struct lhsParseNode *theLHS,
843
+ bool *newChange,
844
+ int depth)
845
+ {
846
+ struct lhsParseNode *argPtr, *lastArg, *nextArg;
847
+ struct lhsParseNode *tempArg;
848
+ bool change;
849
+ struct expr *e1, *e2;
850
+
851
+ /*======================================================*/
852
+ /* Loop through the CEs as long as changes can be made. */
853
+ /*======================================================*/
854
+
855
+ change = true;
856
+ *newChange = false;
857
+
858
+ while (change)
859
+ {
860
+ change = false;
861
+ lastArg = NULL;
862
+
863
+ for (argPtr = theLHS->right;
864
+ argPtr != NULL;)
865
+ {
866
+ /*=====================================*/
867
+ /* Remove duplication of or CEs within */
868
+ /* or CEs and and CEs within and CEs. */
869
+ /*=====================================*/
870
+
871
+ if (((theLHS->pnType == OR_CE_NODE) && (argPtr->pnType == OR_CE_NODE)) ||
872
+ ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == AND_CE_NODE)))
873
+ {
874
+ if (argPtr->logical) theLHS->logical = true;
875
+
876
+ change = true;
877
+ *newChange = true;
878
+ tempArg = argPtr->right;
879
+ nextArg = argPtr->bottom;
880
+ argPtr->right = NULL;
881
+ argPtr->bottom = NULL;
882
+ ReturnLHSParseNodes(theEnv,argPtr);
883
+
884
+ if (lastArg == NULL)
885
+ { theLHS->right = tempArg; }
886
+ else
887
+ { lastArg->bottom = tempArg; }
888
+
889
+ argPtr = tempArg;
890
+ while (tempArg->bottom != NULL) tempArg = tempArg->bottom;
891
+ tempArg->bottom = nextArg;
892
+ }
893
+
894
+ /*=======================================================*/
895
+ /* Replace not CEs containing a test CE with just a test */
896
+ /* CE with the original test CE condition negated. */
897
+ /*=======================================================*/
898
+
899
+ else if ((theLHS->pnType == NOT_CE_NODE) && (argPtr->pnType == TEST_CE_NODE))
900
+ {
901
+ change = true;
902
+ *newChange = true;
903
+
904
+ tempArg = GetLHSParseNode(theEnv);
905
+ tempArg->pnType = FCALL_NODE;
906
+ tempArg->value = ExpressionData(theEnv)->PTR_NOT;
907
+ tempArg->bottom = argPtr->expression;
908
+ argPtr->expression = tempArg;
909
+
910
+ CopyLHSParseNode(theEnv,theLHS,argPtr,true);
911
+ ReturnLHSParseNodes(theEnv,argPtr);
912
+ theLHS->right = NULL;
913
+ break;
914
+ }
915
+
916
+ /*==============================*/
917
+ /* Two adjacent test CEs within */
918
+ /* an and CE can be combined. */
919
+ /*==============================*/
920
+
921
+ else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == TEST_CE_NODE) &&
922
+ ((argPtr->bottom != NULL) ? argPtr->bottom->pnType == TEST_CE_NODE :
923
+ false) &&
924
+ (argPtr->beginNandDepth == argPtr->endNandDepth) &&
925
+ (argPtr->endNandDepth == argPtr->bottom->beginNandDepth))
926
+ {
927
+ change = true;
928
+ *newChange = true;
929
+
930
+ argPtr->expression = CombineLHSParseNodes(theEnv,argPtr->expression,argPtr->bottom->expression);
931
+ argPtr->bottom->expression = NULL;
932
+
933
+ tempArg = argPtr->bottom;
934
+ argPtr->bottom = tempArg->bottom;
935
+ tempArg->bottom = NULL;
936
+
937
+ ReturnLHSParseNodes(theEnv,tempArg);
938
+ }
939
+
940
+ /*========================================================*/
941
+ /* A test CE can be attached to the preceding pattern CE. */
942
+ /*========================================================*/
943
+
944
+ else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == PATTERN_CE_NODE) &&
945
+ ((argPtr->bottom != NULL) ? argPtr->bottom->pnType == TEST_CE_NODE :
946
+ false) &&
947
+ (argPtr->negated == false) &&
948
+ (argPtr->exists == false) &&
949
+ (argPtr->beginNandDepth == argPtr->endNandDepth) &&
950
+ (argPtr->endNandDepth == argPtr->bottom->beginNandDepth))
951
+ {
952
+ int endNandDepth;
953
+ change = true;
954
+ *newChange = true;
955
+
956
+ endNandDepth = argPtr->bottom->endNandDepth;
957
+
958
+ if (argPtr->negated || argPtr->exists)
959
+ {
960
+ e1 = LHSParseNodesToExpression(theEnv,argPtr->secondaryExpression);
961
+ e2 = LHSParseNodesToExpression(theEnv,argPtr->bottom->expression);
962
+ e1 = CombineExpressions(theEnv,e1,e2);
963
+ ReturnLHSParseNodes(theEnv,argPtr->secondaryExpression);
964
+ argPtr->secondaryExpression = ExpressionToLHSParseNodes(theEnv,e1);
965
+ ReturnExpression(theEnv,e1);
966
+ }
967
+ else
968
+ {
969
+ argPtr->expression = CombineLHSParseNodes(theEnv,argPtr->expression,argPtr->bottom->expression);
970
+ argPtr->bottom->expression = NULL;
971
+ }
972
+
973
+ if ((theLHS->right == argPtr) && ((argPtr->beginNandDepth - 1) == endNandDepth))
974
+ {
975
+ if (argPtr->negated)
976
+ {
977
+ argPtr->negated = false;
978
+ argPtr->exists = true;
979
+ e1 = LHSParseNodesToExpression(theEnv,argPtr->secondaryExpression);
980
+ e1 = NegateExpression(theEnv,e1);
981
+ ReturnLHSParseNodes(theEnv,argPtr->secondaryExpression);
982
+ argPtr->secondaryExpression = ExpressionToLHSParseNodes(theEnv,e1);
983
+ ReturnExpression(theEnv,e1);
984
+ }
985
+ else if (argPtr->exists)
986
+ {
987
+ argPtr->negated = true;
988
+ argPtr->exists = false;
989
+ e1 = LHSParseNodesToExpression(theEnv,argPtr->secondaryExpression);
990
+ e1 = NegateExpression(theEnv,e1);
991
+ ReturnLHSParseNodes(theEnv,argPtr->secondaryExpression);
992
+ argPtr->secondaryExpression = ExpressionToLHSParseNodes(theEnv,e1);
993
+ ReturnExpression(theEnv,e1);
994
+ }
995
+ else
996
+ {
997
+ argPtr->negated = true;
998
+ }
999
+ PropagateNandDepth(argPtr,endNandDepth,endNandDepth);
1000
+ }
1001
+
1002
+ /*========================================*/
1003
+ /* Detach the test CE from its parent and */
1004
+ /* dispose of the data structures. */
1005
+ /*========================================*/
1006
+
1007
+ tempArg = argPtr->bottom;
1008
+ argPtr->bottom = tempArg->bottom;
1009
+ tempArg->bottom = NULL;
1010
+
1011
+ ReturnLHSParseNodes(theEnv,tempArg);
1012
+ }
1013
+
1014
+ /*=====================================*/
1015
+ /* Replace and CEs containing a single */
1016
+ /* test CE with just a test CE. */
1017
+ /*=====================================*/
1018
+
1019
+ else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == TEST_CE_NODE) &&
1020
+ (theLHS->right == argPtr) && (argPtr->bottom == NULL))
1021
+ {
1022
+ change = true;
1023
+ *newChange = true;
1024
+
1025
+ CopyLHSParseNode(theEnv,theLHS,argPtr,true);
1026
+ theLHS->right = NULL;
1027
+ ReturnLHSParseNodes(theEnv,argPtr);
1028
+ break;
1029
+ }
1030
+
1031
+ /*=======================================================*/
1032
+ /* Replace and CEs containing a single pattern CE with */
1033
+ /* just a pattern CE if this is not the top most and CE. */
1034
+ /*=======================================================*/
1035
+
1036
+ else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == PATTERN_CE_NODE) &&
1037
+ (theLHS->right == argPtr) && (argPtr->bottom == NULL) && (depth > 1))
1038
+ {
1039
+ change = true;
1040
+ *newChange = true;
1041
+
1042
+ CopyLHSParseNode(theEnv,theLHS,argPtr,false);
1043
+
1044
+ theLHS->right = argPtr->right;
1045
+
1046
+ argPtr->networkTest = NULL;
1047
+ argPtr->externalNetworkTest = NULL;
1048
+ argPtr->secondaryNetworkTest = NULL;
1049
+ argPtr->externalRightHash = NULL;
1050
+ argPtr->externalLeftHash = NULL;
1051
+ argPtr->constantSelector = NULL;
1052
+ argPtr->constantValue = NULL;
1053
+ argPtr->leftHash = NULL;
1054
+ argPtr->rightHash = NULL;
1055
+ argPtr->betaHash = NULL;
1056
+ argPtr->expression = NULL;
1057
+ argPtr->secondaryExpression = NULL;
1058
+ argPtr->userData = NULL;
1059
+ argPtr->right = NULL;
1060
+ argPtr->bottom = NULL;
1061
+ ReturnLHSParseNodes(theEnv,argPtr);
1062
+ break;
1063
+ }
1064
+
1065
+ /*===================================================*/
1066
+ /* If no changes are needed, move on to the next CE. */
1067
+ /*===================================================*/
1068
+
1069
+ else
1070
+ {
1071
+ lastArg = argPtr;
1072
+ argPtr = argPtr->bottom;
1073
+ }
1074
+ }
1075
+ }
1076
+
1077
+ /*===========================*/
1078
+ /* Return the reordered LHS. */
1079
+ /*===========================*/
1080
+
1081
+ return(theLHS);
1082
+ }
1083
+
1084
+ /*********************************************************************/
1085
+ /* CopyLHSParseNodes: Copies a linked group of conditional elements. */
1086
+ /*********************************************************************/
1087
+ struct lhsParseNode *CopyLHSParseNodes(
1088
+ Environment *theEnv,
1089
+ struct lhsParseNode *listOfCEs)
1090
+ {
1091
+ struct lhsParseNode *newList;
1092
+
1093
+ if (listOfCEs == NULL)
1094
+ { return NULL; }
1095
+
1096
+ newList = get_struct(theEnv,lhsParseNode);
1097
+ CopyLHSParseNode(theEnv,newList,listOfCEs,true);
1098
+
1099
+ newList->right = CopyLHSParseNodes(theEnv,listOfCEs->right);
1100
+ newList->bottom = CopyLHSParseNodes(theEnv,listOfCEs->bottom);
1101
+
1102
+ return(newList);
1103
+ }
1104
+
1105
+ /**********************************************************/
1106
+ /* CopyLHSParseNode: Copies a single conditional element. */
1107
+ /**********************************************************/
1108
+ void CopyLHSParseNode(
1109
+ Environment *theEnv,
1110
+ struct lhsParseNode *dest,
1111
+ struct lhsParseNode *src,
1112
+ bool duplicate)
1113
+ {
1114
+ dest->pnType = src->pnType;
1115
+ dest->value = src->value;
1116
+ dest->negated = src->negated;
1117
+ dest->exists = src->exists;
1118
+ dest->existsNand = src->existsNand;
1119
+ dest->bindingVariable = src->bindingVariable;
1120
+ dest->withinMultifieldSlot = src->withinMultifieldSlot;
1121
+ dest->multifieldSlot = src->multifieldSlot;
1122
+ dest->multiFieldsBefore = src->multiFieldsBefore;
1123
+ dest->multiFieldsAfter = src->multiFieldsAfter;
1124
+ dest->singleFieldsBefore = src->singleFieldsBefore;
1125
+ dest->singleFieldsAfter = src->singleFieldsAfter;
1126
+ dest->logical = src->logical;
1127
+ dest->userCE = src->userCE;
1128
+ //dest->marked = src->marked;
1129
+ dest->whichCE = src->whichCE;
1130
+ dest->referringNode = src->referringNode;
1131
+ dest->patternType = src->patternType;
1132
+ dest->pattern = src->pattern;
1133
+ dest->index = src->index;
1134
+ dest->slot = src->slot;
1135
+ dest->slotNumber = src->slotNumber;
1136
+ dest->beginNandDepth = src->beginNandDepth;
1137
+ dest->endNandDepth = src->endNandDepth;
1138
+ dest->joinDepth = src->joinDepth;
1139
+
1140
+ /*==========================================================*/
1141
+ /* The duplicate flag controls whether pointers to existing */
1142
+ /* data structures are used when copying some slots or if */
1143
+ /* new copies of the data structures are made. */
1144
+ /*==========================================================*/
1145
+
1146
+ if (duplicate)
1147
+ {
1148
+ dest->networkTest = CopyExpression(theEnv,src->networkTest);
1149
+ dest->externalNetworkTest = CopyExpression(theEnv,src->externalNetworkTest);
1150
+ dest->secondaryNetworkTest = CopyExpression(theEnv,src->secondaryNetworkTest);
1151
+ dest->externalRightHash = CopyExpression(theEnv,src->externalRightHash);
1152
+ dest->externalLeftHash = CopyExpression(theEnv,src->externalLeftHash);
1153
+ dest->constantSelector = CopyExpression(theEnv,src->constantSelector);
1154
+ dest->constantValue = CopyExpression(theEnv,src->constantValue);
1155
+ dest->leftHash = CopyExpression(theEnv,src->leftHash);
1156
+ dest->betaHash = CopyExpression(theEnv,src->betaHash);
1157
+ dest->rightHash = CopyExpression(theEnv,src->rightHash);
1158
+ if (src->userData == NULL)
1159
+ { dest->userData = NULL; }
1160
+ else if (src->patternType->copyUserDataFunction == NULL)
1161
+ { dest->userData = src->userData; }
1162
+ else
1163
+ { dest->userData = (*src->patternType->copyUserDataFunction)(theEnv,src->userData); }
1164
+ dest->expression = CopyLHSParseNodes(theEnv,src->expression);
1165
+ dest->secondaryExpression = CopyLHSParseNodes(theEnv,src->secondaryExpression);
1166
+ dest->constraints = CopyConstraintRecord(theEnv,src->constraints);
1167
+ if (dest->constraints != NULL) dest->derivedConstraints = true;
1168
+ else dest->derivedConstraints = false;
1169
+ }
1170
+ else
1171
+ {
1172
+ dest->networkTest = src->networkTest;
1173
+ dest->externalNetworkTest = src->externalNetworkTest;
1174
+ dest->secondaryNetworkTest = src->secondaryNetworkTest;
1175
+ dest->externalRightHash = src->externalRightHash;
1176
+ dest->externalLeftHash = src->externalLeftHash;
1177
+ dest->constantSelector = src->constantSelector;
1178
+ dest->constantValue = src->constantValue;
1179
+ dest->leftHash = src->leftHash;
1180
+ dest->betaHash = src->betaHash;
1181
+ dest->rightHash = src->rightHash;
1182
+ dest->userData = src->userData;
1183
+ dest->expression = src->expression;
1184
+ dest->secondaryExpression = src->secondaryExpression;
1185
+ dest->derivedConstraints = false;
1186
+ dest->constraints = src->constraints;
1187
+ }
1188
+ }
1189
+
1190
+ /****************************************************/
1191
+ /* GetLHSParseNode: Creates an empty node structure */
1192
+ /* used for building conditional elements. */
1193
+ /****************************************************/
1194
+ struct lhsParseNode *GetLHSParseNode(
1195
+ Environment *theEnv)
1196
+ {
1197
+ struct lhsParseNode *newNode;
1198
+
1199
+ newNode = get_struct(theEnv,lhsParseNode);
1200
+ newNode->pnType = UNKNOWN_NODE;
1201
+ newNode->value = NULL;
1202
+ newNode->negated = false;
1203
+ newNode->exists = false;
1204
+ newNode->existsNand = false;
1205
+ newNode->bindingVariable = false;
1206
+ newNode->withinMultifieldSlot = false;
1207
+ newNode->multifieldSlot = false;
1208
+ newNode->multiFieldsBefore = 0;
1209
+ newNode->multiFieldsAfter = 0;
1210
+ newNode->singleFieldsBefore = 0;
1211
+ newNode->singleFieldsAfter = 0;
1212
+ newNode->logical = false;
1213
+ newNode->derivedConstraints = false;
1214
+ newNode->userCE = true;
1215
+ //newNode->marked = false;
1216
+ newNode->whichCE = 0;
1217
+ newNode->constraints = NULL;
1218
+ newNode->referringNode = NULL;
1219
+ newNode->patternType = NULL;
1220
+ newNode->pattern = -1;
1221
+ newNode->index = NO_INDEX;
1222
+ newNode->slot = NULL;
1223
+ newNode->slotNumber = UNSPECIFIED_SLOT;
1224
+ newNode->beginNandDepth = 1;
1225
+ newNode->endNandDepth = 1;
1226
+ newNode->joinDepth = 0;
1227
+ newNode->userData = NULL;
1228
+ newNode->networkTest = NULL;
1229
+ newNode->externalNetworkTest = NULL;
1230
+ newNode->secondaryNetworkTest = NULL;
1231
+ newNode->externalRightHash = NULL;
1232
+ newNode->externalLeftHash = NULL;
1233
+ newNode->constantSelector = NULL;
1234
+ newNode->constantValue = NULL;
1235
+ newNode->leftHash = NULL;
1236
+ newNode->betaHash = NULL;
1237
+ newNode->rightHash = NULL;
1238
+ newNode->expression = NULL;
1239
+ newNode->secondaryExpression = NULL;
1240
+ newNode->right = NULL;
1241
+ newNode->bottom = NULL;
1242
+
1243
+ return(newNode);
1244
+ }
1245
+
1246
+ /********************************************************/
1247
+ /* ReturnLHSParseNodes: Returns a multiply linked list */
1248
+ /* of lhsParseNode structures to the memory manager. */
1249
+ /********************************************************/
1250
+ void ReturnLHSParseNodes(
1251
+ Environment *theEnv,
1252
+ struct lhsParseNode *waste)
1253
+ {
1254
+ if (waste != NULL)
1255
+ {
1256
+ ReturnExpression(theEnv,waste->networkTest);
1257
+ ReturnExpression(theEnv,waste->externalNetworkTest);
1258
+ ReturnExpression(theEnv,waste->secondaryNetworkTest);
1259
+ ReturnExpression(theEnv,waste->externalRightHash);
1260
+ ReturnExpression(theEnv,waste->externalLeftHash);
1261
+ ReturnExpression(theEnv,waste->constantSelector);
1262
+ ReturnExpression(theEnv,waste->constantValue);
1263
+ ReturnExpression(theEnv,waste->leftHash);
1264
+ ReturnExpression(theEnv,waste->betaHash);
1265
+ ReturnExpression(theEnv,waste->rightHash);
1266
+ ReturnLHSParseNodes(theEnv,waste->right);
1267
+ ReturnLHSParseNodes(theEnv,waste->bottom);
1268
+ ReturnLHSParseNodes(theEnv,waste->expression);
1269
+ ReturnLHSParseNodes(theEnv,waste->secondaryExpression);
1270
+ if (waste->derivedConstraints) RemoveConstraint(theEnv,waste->constraints);
1271
+ if ((waste->userData != NULL) &&
1272
+ (waste->patternType->returnUserDataFunction != NULL))
1273
+ { (*waste->patternType->returnUserDataFunction)(theEnv,waste->userData); }
1274
+ rtn_struct(theEnv,lhsParseNode,waste);
1275
+ }
1276
+ }
1277
+
1278
+ /********************************************************/
1279
+ /* ExpressionToLHSParseNodes: Copies an expression into */
1280
+ /* the equivalent lhsParseNode data structures. */
1281
+ /********************************************************/
1282
+ struct lhsParseNode *ExpressionToLHSParseNodes(
1283
+ Environment *theEnv,
1284
+ struct expr *expressionList)
1285
+ {
1286
+ struct lhsParseNode *newList, *theList;
1287
+ struct functionDefinition *theFunction;
1288
+ unsigned int i;
1289
+ unsigned theRestriction2;
1290
+
1291
+ /*===========================================*/
1292
+ /* A NULL expression requires no conversion. */
1293
+ /*===========================================*/
1294
+
1295
+ if (expressionList == NULL) return NULL;
1296
+
1297
+ /*====================================*/
1298
+ /* Recursively convert the expression */
1299
+ /* to lhsParseNode data structures. */
1300
+ /*====================================*/
1301
+
1302
+ newList = GetLHSParseNode(theEnv);
1303
+ newList->pnType = TypeToNodeType(expressionList->type);
1304
+ newList->value = expressionList->value;
1305
+ newList->right = ExpressionToLHSParseNodes(theEnv,expressionList->nextArg);
1306
+ newList->bottom = ExpressionToLHSParseNodes(theEnv,expressionList->argList);
1307
+
1308
+ /*==================================================*/
1309
+ /* If the expression is a function call, then store */
1310
+ /* the constraint information for the functions */
1311
+ /* arguments in the lshParseNode data structures. */
1312
+ /*==================================================*/
1313
+
1314
+ if (newList->pnType != FCALL_NODE) return(newList);
1315
+
1316
+ theFunction = newList->functionValue;
1317
+ for (theList = newList->bottom, i = 1;
1318
+ theList != NULL;
1319
+ theList = theList->right, i++)
1320
+ {
1321
+ if (theList->pnType == SF_VARIABLE_NODE)
1322
+ {
1323
+ theRestriction2 = GetNthRestriction(theEnv,theFunction,i);
1324
+ theList->constraints = ArgumentTypeToConstraintRecord(theEnv,theRestriction2);
1325
+ theList->derivedConstraints = true;
1326
+ }
1327
+ }
1328
+
1329
+ /*==================================*/
1330
+ /* Return the converted expression. */
1331
+ /*==================================*/
1332
+
1333
+ return(newList);
1334
+ }
1335
+
1336
+ /******************************************************************/
1337
+ /* LHSParseNodesToExpression: Copies lhsParseNode data structures */
1338
+ /* into the equivalent expression data structures. */
1339
+ /******************************************************************/
1340
+ struct expr *LHSParseNodesToExpression(
1341
+ Environment *theEnv,
1342
+ struct lhsParseNode *nodeList)
1343
+ {
1344
+ struct expr *newList;
1345
+
1346
+ if (nodeList == NULL)
1347
+ { return NULL; }
1348
+
1349
+ newList = get_struct(theEnv,expr);
1350
+ newList->type = NodeTypeToType(nodeList);
1351
+ newList->value = nodeList->value;
1352
+ newList->nextArg = LHSParseNodesToExpression(theEnv,nodeList->right);
1353
+ newList->argList = LHSParseNodesToExpression(theEnv,nodeList->bottom);
1354
+
1355
+ return(newList);
1356
+ }
1357
+
1358
+ /******************************************/
1359
+ /* ConstantNode: Returns true if the node */
1360
+ /* is a constant, otherwise false. */
1361
+ /******************************************/
1362
+ bool ConstantNode(
1363
+ struct lhsParseNode *theNode)
1364
+ {
1365
+ switch (theNode->pnType)
1366
+ {
1367
+ case SYMBOL_NODE:
1368
+ case STRING_NODE:
1369
+ case INTEGER_NODE:
1370
+ case FLOAT_NODE:
1371
+ #if OBJECT_SYSTEM
1372
+ case INSTANCE_NAME_NODE:
1373
+ #endif
1374
+ return true;
1375
+
1376
+ default:
1377
+ return false;
1378
+ }
1379
+
1380
+ return false;
1381
+ }
1382
+
1383
+ /*******************/
1384
+ /* NodeTypeToType: */
1385
+ /*******************/
1386
+ unsigned short NodeTypeToType(
1387
+ struct lhsParseNode *theNode)
1388
+ {
1389
+ switch (theNode->pnType)
1390
+ {
1391
+ case FLOAT_NODE:
1392
+ return FLOAT_TYPE;
1393
+ case INTEGER_NODE:
1394
+ return INTEGER_TYPE;
1395
+ case SYMBOL_NODE:
1396
+ return SYMBOL_TYPE;
1397
+ case STRING_NODE:
1398
+ return STRING_TYPE;
1399
+ case INSTANCE_NAME_NODE:
1400
+ return INSTANCE_NAME_TYPE;
1401
+ case SF_VARIABLE_NODE:
1402
+ return SF_VARIABLE;
1403
+ case MF_VARIABLE_NODE:
1404
+ return MF_VARIABLE;
1405
+ case GBL_VARIABLE_NODE:
1406
+ return GBL_VARIABLE;
1407
+ case FCALL_NODE:
1408
+ return FCALL;
1409
+ case PCALL_NODE:
1410
+ return PCALL;
1411
+ case GCALL_NODE:
1412
+ return GCALL;
1413
+ case FACT_STORE_MULTIFIELD_NODE:
1414
+ return FACT_STORE_MULTIFIELD;
1415
+ case DEFTEMPLATE_PTR_NODE:
1416
+ return DEFTEMPLATE_PTR;
1417
+ case DEFCLASS_PTR_NODE:
1418
+ return DEFCLASS_PTR;
1419
+
1420
+ default:
1421
+ return VOID_TYPE;
1422
+ }
1423
+ }
1424
+
1425
+ /*******************/
1426
+ /* TypeToNodeType: */
1427
+ /*******************/
1428
+ ParseNodeType TypeToNodeType(
1429
+ unsigned short theType)
1430
+ {
1431
+ switch (theType)
1432
+ {
1433
+ case FLOAT_TYPE:
1434
+ return FLOAT_NODE;
1435
+ case INTEGER_TYPE:
1436
+ return INTEGER_NODE;
1437
+ case SYMBOL_TYPE:
1438
+ return SYMBOL_NODE;
1439
+ case STRING_TYPE:
1440
+ return STRING_NODE;
1441
+ case INSTANCE_NAME_TYPE:
1442
+ return INSTANCE_NAME_NODE;
1443
+ case SF_VARIABLE:
1444
+ return SF_VARIABLE_NODE;
1445
+ case MF_VARIABLE:
1446
+ return MF_VARIABLE_NODE;
1447
+ case GBL_VARIABLE:
1448
+ return GBL_VARIABLE_NODE;
1449
+ case FCALL:
1450
+ return FCALL_NODE;
1451
+ case PCALL:
1452
+ return PCALL_NODE;
1453
+ case GCALL:
1454
+ return GCALL_NODE;
1455
+ case FACT_STORE_MULTIFIELD:
1456
+ return FACT_STORE_MULTIFIELD_NODE;
1457
+ case DEFTEMPLATE_PTR:
1458
+ return DEFTEMPLATE_PTR_NODE;
1459
+ case DEFCLASS_PTR:
1460
+ return DEFCLASS_PTR_NODE;
1461
+
1462
+ default:
1463
+ return UNKNOWN_NODE;
1464
+ }
1465
+ }
1466
+
1467
+ /************************************************************/
1468
+ /* IncrementNandDepth: Increments the nand depth of a group */
1469
+ /* of CEs. The nand depth is used to indicate the nesting */
1470
+ /* of not/and or not/not CEs which are implemented using */
1471
+ /* joins from the right. A single pattern within a "not" */
1472
+ /* CE does not require a join from the right and its nand */
1473
+ /* depth is normally not increased (except when it's */
1474
+ /* within a not/and or not/not CE. The begin nand depth */
1475
+ /* indicates the current nesting for a CE. The end nand */
1476
+ /* depth indicates the nand depth in the following CE */
1477
+ /* (assuming that the next CE is not the beginning of a */
1478
+ /* new group of nand CEs). All but the last CE in a nand */
1479
+ /* group should have the same begin and end nand depths. */
1480
+ /* Since a single CE can be the last CE of several nand */
1481
+ /* groups, it is possible to have an end nand depth that */
1482
+ /* is more than 1 less than the begin nand depth of the */
1483
+ /* CE. */
1484
+ /************************************************************/
1485
+ static void IncrementNandDepth(
1486
+ Environment *theEnv,
1487
+ struct lhsParseNode *theLHS,
1488
+ bool lastCE)
1489
+ {
1490
+ /*======================================*/
1491
+ /* Loop through each CE in the group of */
1492
+ /* CEs having its nand depth increased. */
1493
+ /*======================================*/
1494
+
1495
+ for (;
1496
+ theLHS != NULL;
1497
+ theLHS = theLHS->bottom)
1498
+ {
1499
+ /*=========================================================*/
1500
+ /* Increment the begin nand depth of pattern and test CEs. */
1501
+ /* The last CE in the original list doesn't have its end */
1502
+ /* nand depth incremented. All other last CEs in other CEs */
1503
+ /* entered recursively do have their end depth incremented */
1504
+ /* (unless the last CE in the recursively entered CE is */
1505
+ /* the same last CE as contained in the original group */
1506
+ /* when this function was first entered). */
1507
+ /*=========================================================*/
1508
+
1509
+ if ((theLHS->pnType == PATTERN_CE_NODE) || (theLHS->pnType == TEST_CE_NODE))
1510
+ {
1511
+ theLHS->beginNandDepth++;
1512
+
1513
+ if (lastCE == false) theLHS->endNandDepth++;
1514
+ else if (theLHS->bottom != NULL) theLHS->endNandDepth++;
1515
+ }
1516
+
1517
+ /*==============================================*/
1518
+ /* Recursively increase the nand depth of other */
1519
+ /* CEs contained within the CE having its nand */
1520
+ /* depth increased. */
1521
+ /*==============================================*/
1522
+
1523
+ else if ((theLHS->pnType == AND_CE_NODE) || (theLHS->pnType == NOT_CE_NODE))
1524
+ {
1525
+ IncrementNandDepth(theEnv,theLHS->right,
1526
+ (lastCE ? (theLHS->bottom == NULL) : false));
1527
+ }
1528
+
1529
+ /*=====================================*/
1530
+ /* All or CEs should have been removed */
1531
+ /* from the LHS at this point. */
1532
+ /*=====================================*/
1533
+
1534
+ else if (theLHS->pnType == OR_CE_NODE)
1535
+ { SystemError(theEnv,"REORDER",1); }
1536
+ }
1537
+ }
1538
+
1539
+ /***********************************************************/
1540
+ /* CreateInitialPattern: Creates a default pattern used in */
1541
+ /* the LHS of a rule under certain cirmustances (such as */
1542
+ /* when a "not" or "test" CE is the first CE in an "and" */
1543
+ /* CE or when no CEs are specified in the LHS of a rule. */
1544
+ /***********************************************************/
1545
+ static struct lhsParseNode *CreateInitialPattern(
1546
+ Environment *theEnv)
1547
+ {
1548
+ struct lhsParseNode *topNode;
1549
+
1550
+ /*==========================================*/
1551
+ /* Create the top most node of the pattern. */
1552
+ /*==========================================*/
1553
+
1554
+ topNode = GetLHSParseNode(theEnv);
1555
+ topNode->pnType = PATTERN_CE_NODE;
1556
+ topNode->userCE = false;
1557
+ topNode->bottom = NULL;
1558
+
1559
+ return(topNode);
1560
+ }
1561
+
1562
+ /*****************************************************************/
1563
+ /* AddRemainingInitialPatterns: Finishes adding initial patterns */
1564
+ /* where needed on the LHS of a rule. Assumes that an initial */
1565
+ /* pattern has been added to the beginning of the rule if one */
1566
+ /* was needed. */
1567
+ /*****************************************************************/
1568
+ static struct lhsParseNode *AddRemainingInitialPatterns(
1569
+ Environment *theEnv,
1570
+ struct lhsParseNode *theLHS)
1571
+ {
1572
+ struct lhsParseNode *lastNode = NULL, *thePattern, *rv = theLHS;
1573
+ int currentDepth = 1;
1574
+
1575
+ while (theLHS != NULL)
1576
+ {
1577
+ if ((theLHS->pnType == TEST_CE_NODE) &&
1578
+ (theLHS->beginNandDepth > currentDepth))
1579
+ {
1580
+ thePattern = CreateInitialPattern(theEnv);
1581
+ thePattern->beginNandDepth = theLHS->beginNandDepth;
1582
+ thePattern->endNandDepth = theLHS->beginNandDepth;
1583
+ thePattern->logical = theLHS->logical;
1584
+ thePattern->existsNand = theLHS->existsNand;
1585
+ theLHS->existsNand = false;
1586
+
1587
+ thePattern->bottom = theLHS;
1588
+
1589
+ if (lastNode == NULL)
1590
+ { rv = thePattern; }
1591
+ else
1592
+ { lastNode->bottom = thePattern; }
1593
+ }
1594
+
1595
+ lastNode = theLHS;
1596
+ currentDepth = theLHS->endNandDepth;
1597
+ theLHS = theLHS->bottom;
1598
+ }
1599
+
1600
+ return(rv);
1601
+ }
1602
+
1603
+ /*************************************************************/
1604
+ /* AssignPatternIndices: For each pattern CE in the LHS of a */
1605
+ /* rule, determines the pattern index for the CE. A simple */
1606
+ /* 1 to N numbering can't be used since a join from the */
1607
+ /* right only counts as a single CE to other CEs outside */
1608
+ /* the lexical scope of the join from the right. For */
1609
+ /* example, the patterns in the following LHS */
1610
+ /* */
1611
+ /* (a) (not (b) (c) (d)) (e) */
1612
+ /* */
1613
+ /* would be assigned the following numbers: a-1, b-2, c-3, */
1614
+ /* d-4, and e-3. */
1615
+ /*************************************************************/
1616
+ static struct lhsParseNode *AssignPatternIndices(
1617
+ struct lhsParseNode *theLHS,
1618
+ short startIndex,
1619
+ int nandDepth,
1620
+ unsigned short joinDepth)
1621
+ {
1622
+ struct lhsParseNode *theField;
1623
+
1624
+ /*====================================*/
1625
+ /* Loop through the CEs at this level */
1626
+ /* assigning each CE a pattern index. */
1627
+ /*====================================*/
1628
+
1629
+ while (theLHS != NULL)
1630
+ {
1631
+ /*============================================================*/
1632
+ /* If we're entering a group of CEs requiring a join from the */
1633
+ /* right, compute the pattern indices for that group and then */
1634
+ /* proceed with the next CE in this group. A join from the */
1635
+ /* right only counts as one CE on this level regardless of */
1636
+ /* the number of CEs it contains. If the end of this level is */
1637
+ /* encountered while processing the join from right, then */
1638
+ /* return to the previous level. */
1639
+ /*============================================================*/
1640
+
1641
+ if (theLHS->beginNandDepth > nandDepth)
1642
+ {
1643
+ theLHS = AssignPatternIndices(theLHS,startIndex,nandDepth+1,joinDepth);
1644
+
1645
+ if (theLHS->endNandDepth < nandDepth) return(theLHS);
1646
+ startIndex++;
1647
+ joinDepth++;
1648
+ }
1649
+
1650
+ /*=====================================================*/
1651
+ /* A test CE is not assigned a pattern index, however, */
1652
+ /* if it is the last CE at the end of this level, then */
1653
+ /* return to the previous level. If this is the first */
1654
+ /* CE in a group, it will have a join created so the */
1655
+ /* depth should be incremented. */
1656
+ /*=====================================================*/
1657
+
1658
+ else if (theLHS->pnType == TEST_CE_NODE)
1659
+ {
1660
+ if (joinDepth == 0)
1661
+ { joinDepth++; }
1662
+ theLHS->joinDepth = joinDepth - 1;
1663
+ PropagateJoinDepth(theLHS->expression,joinDepth - 1);
1664
+ PropagateNandDepth(theLHS->expression,theLHS->beginNandDepth,theLHS->endNandDepth);
1665
+ if (theLHS->endNandDepth < nandDepth) return(theLHS);
1666
+ }
1667
+
1668
+ /*==========================================================*/
1669
+ /* The fields of a pattern CE need to be assigned a pattern */
1670
+ /* index, field index, and/or slot names. If this CE is the */
1671
+ /* last CE at the end of this level, then return to the */
1672
+ /* previous level. */
1673
+ /*==========================================================*/
1674
+
1675
+ else if (theLHS->pnType == PATTERN_CE_NODE)
1676
+ {
1677
+ if (theLHS->expression != NULL)
1678
+ {
1679
+ PropagateJoinDepth(theLHS->expression,joinDepth);
1680
+ PropagateNandDepth(theLHS->expression,theLHS->beginNandDepth,theLHS->endNandDepth);
1681
+ }
1682
+
1683
+ theLHS->pattern = startIndex;
1684
+ theLHS->joinDepth = joinDepth;
1685
+ PropagateJoinDepth(theLHS->right,joinDepth);
1686
+ PropagateNandDepth(theLHS->right,theLHS->beginNandDepth,theLHS->endNandDepth);
1687
+ for (theField = theLHS->right; theField != NULL; theField = theField->right)
1688
+ {
1689
+ theField->pattern = startIndex;
1690
+ PropagateIndexSlotPatternValues(theField,theField->pattern,
1691
+ theField->index,theField->slot,
1692
+ theField->slotNumber);
1693
+ }
1694
+
1695
+ if (theLHS->endNandDepth < nandDepth) return(theLHS);
1696
+ startIndex++;
1697
+ joinDepth++;
1698
+ }
1699
+
1700
+ /*=========================*/
1701
+ /* Move on to the next CE. */
1702
+ /*=========================*/
1703
+
1704
+ theLHS = theLHS->bottom;
1705
+ }
1706
+
1707
+ /*========================================*/
1708
+ /* There are no more CEs left to process. */
1709
+ /* Return to the previous level. */
1710
+ /*========================================*/
1711
+
1712
+ return NULL;
1713
+ }
1714
+
1715
+ /***********************************************************/
1716
+ /* PropagateIndexSlotPatternValues: Assigns pattern, field */
1717
+ /* and slot identifiers to a field in a pattern. */
1718
+ /***********************************************************/
1719
+ static void PropagateIndexSlotPatternValues(
1720
+ struct lhsParseNode *theField,
1721
+ short thePattern,
1722
+ unsigned short theIndex,
1723
+ CLIPSLexeme *theSlot,
1724
+ unsigned short theSlotNumber)
1725
+ {
1726
+ struct lhsParseNode *tmpNode, *andField;
1727
+
1728
+ /*=============================================*/
1729
+ /* A NULL field does not have to be processed. */
1730
+ /*=============================================*/
1731
+
1732
+ if (theField == NULL) return;
1733
+
1734
+ /*=====================================================*/
1735
+ /* Assign the appropriate identifiers for a multifield */
1736
+ /* slot by calling this routine recursively. */
1737
+ /*=====================================================*/
1738
+
1739
+ if (theField->multifieldSlot)
1740
+ {
1741
+ theField->pattern = thePattern;
1742
+ if ((theIndex > 0) && (theIndex != NO_INDEX))
1743
+ { theField->index = theIndex; }
1744
+ theField->slot = theSlot;
1745
+ theField->slotNumber = theSlotNumber;
1746
+
1747
+ for (tmpNode = theField->bottom;
1748
+ tmpNode != NULL;
1749
+ tmpNode = tmpNode->right)
1750
+ {
1751
+ tmpNode->pattern = thePattern;
1752
+ tmpNode->slot = theSlot;
1753
+ PropagateIndexSlotPatternValues(tmpNode,thePattern,tmpNode->index,
1754
+ theSlot,theSlotNumber);
1755
+ }
1756
+
1757
+ return;
1758
+ }
1759
+
1760
+ /*=======================================================*/
1761
+ /* Loop through each of the or'ed constraints (connected */
1762
+ /* by a |) in this field of the pattern. */
1763
+ /*=======================================================*/
1764
+
1765
+ for (theField = theField->bottom;
1766
+ theField != NULL;
1767
+ theField = theField->bottom)
1768
+ {
1769
+ /*===========================================================*/
1770
+ /* Loop through each of the and'ed constraints (connected by */
1771
+ /* a &) in this field of the pattern. Assign the pattern, */
1772
+ /* field, and slot identifiers. */
1773
+ /*===========================================================*/
1774
+
1775
+ for (andField = theField; andField != NULL; andField = andField->right)
1776
+ {
1777
+ andField->pattern = thePattern;
1778
+ if ((theIndex > 0) && (theIndex != NO_INDEX))
1779
+ { andField->index = theIndex; }
1780
+ andField->slot = theSlot;
1781
+ andField->slotNumber = theSlotNumber;
1782
+ }
1783
+ }
1784
+ }
1785
+
1786
+ /***************************************************/
1787
+ /* AssignPatternMarkedFlag: Recursively assigns */
1788
+ /* value to the marked field of a LHSParseNode. */
1789
+ /***************************************************/
1790
+ /*
1791
+ void AssignPatternMarkedFlag(
1792
+ struct lhsParseNode *theField,
1793
+ short markedValue)
1794
+ {
1795
+ while (theField != NULL)
1796
+ {
1797
+ theField->marked = markedValue;
1798
+ if (theField->bottom != NULL)
1799
+ { AssignPatternMarkedFlag(theField->bottom,markedValue); }
1800
+ if (theField->expression != NULL)
1801
+ { AssignPatternMarkedFlag(theField->expression,markedValue); }
1802
+ if (theField->secondaryExpression != NULL)
1803
+ { AssignPatternMarkedFlag(theField->secondaryExpression,markedValue); }
1804
+ theField = theField->right;
1805
+ }
1806
+ }
1807
+ */
1808
+ /*****************************************************************/
1809
+ /* PropagateJoinDepth: Recursively assigns a joinDepth to each */
1810
+ /* node in a LHS node by following the right and bottom links. */
1811
+ /*****************************************************************/
1812
+ static void PropagateJoinDepth(
1813
+ struct lhsParseNode *theField,
1814
+ unsigned short joinDepth)
1815
+ {
1816
+ while (theField != NULL)
1817
+ {
1818
+ theField->joinDepth = joinDepth;
1819
+ if (theField->bottom != NULL)
1820
+ { PropagateJoinDepth(theField->bottom,joinDepth); }
1821
+ if (theField->expression != NULL)
1822
+ { PropagateJoinDepth(theField->expression,joinDepth); }
1823
+ if (theField->secondaryExpression != NULL)
1824
+ { PropagateJoinDepth(theField->secondaryExpression,joinDepth); }
1825
+ theField = theField->right;
1826
+ }
1827
+ }
1828
+
1829
+ /**************************************************************/
1830
+ /* PropagateNandDepth: Recursively assigns the not/and (nand) */
1831
+ /* depth to each node in a LHS node by following the right, */
1832
+ /* bottom, and expression links. */
1833
+ /**************************************************************/
1834
+ static void PropagateNandDepth(
1835
+ struct lhsParseNode *theField,
1836
+ int beginDepth,
1837
+ int endDepth)
1838
+ {
1839
+ if (theField == NULL) return;
1840
+
1841
+ for (; theField != NULL; theField = theField->right)
1842
+ {
1843
+ theField->beginNandDepth = beginDepth;
1844
+ theField->endNandDepth = endDepth;
1845
+ PropagateNandDepth(theField->expression,beginDepth,endDepth);
1846
+ PropagateNandDepth(theField->secondaryExpression,beginDepth,endDepth);
1847
+ PropagateNandDepth(theField->bottom,beginDepth,endDepth);
1848
+ }
1849
+ }
1850
+
1851
+ /*****************************************/
1852
+ /* PropagateWhichCE: Recursively assigns */
1853
+ /* an index indicating the user CE. */
1854
+ /*****************************************/
1855
+ static unsigned short PropagateWhichCE(
1856
+ struct lhsParseNode *theField,
1857
+ unsigned short whichCE)
1858
+ {
1859
+ while (theField != NULL)
1860
+ {
1861
+ if ((theField->pnType == PATTERN_CE_NODE) || (theField->pnType == TEST_CE_NODE))
1862
+ { whichCE++; }
1863
+
1864
+ theField->whichCE = whichCE;
1865
+
1866
+ whichCE = PropagateWhichCE(theField->right,whichCE);
1867
+ PropagateWhichCE(theField->expression,whichCE);
1868
+
1869
+ theField = theField->bottom;
1870
+ }
1871
+
1872
+ return whichCE;
1873
+ }
1874
+
1875
+ /********************/
1876
+ /* IsExistsSubjoin: */
1877
+ /********************/
1878
+ bool IsExistsSubjoin(
1879
+ struct lhsParseNode *theLHS,
1880
+ int parentDepth)
1881
+ {
1882
+ int startDepth = theLHS->beginNandDepth;
1883
+
1884
+ if ((startDepth - parentDepth) != 2)
1885
+ { return false; }
1886
+
1887
+ while (theLHS->endNandDepth >= startDepth)
1888
+ { theLHS = theLHS->bottom; }
1889
+
1890
+ if (theLHS->endNandDepth <= parentDepth)
1891
+ { return true; }
1892
+
1893
+ return false;
1894
+ }
1895
+
1896
+ /***************************************************************************/
1897
+ /* CombineLHSParseNodes: Combines two expressions into a single equivalent */
1898
+ /* expression. Mainly serves to merge expressions containing "and" */
1899
+ /* and "or" expressions without unnecessary duplication of the "and" */
1900
+ /* and "or" expressions (i.e., two "and" expressions can be merged by */
1901
+ /* placing them as arguments within another "and" expression, but it */
1902
+ /* is more efficient to add the arguments of one of the "and" */
1903
+ /* expressions to the list of arguments for the other and expression). */
1904
+ /***************************************************************************/
1905
+ struct lhsParseNode *CombineLHSParseNodes(
1906
+ Environment *theEnv,
1907
+ struct lhsParseNode *expr1,
1908
+ struct lhsParseNode *expr2)
1909
+ {
1910
+ struct lhsParseNode *tempPtr;
1911
+
1912
+ /*===========================================================*/
1913
+ /* If the 1st expression is NULL, return the 2nd expression. */
1914
+ /*===========================================================*/
1915
+
1916
+ if (expr1 == NULL) return(expr2);
1917
+
1918
+ /*===========================================================*/
1919
+ /* If the 2nd expression is NULL, return the 1st expression. */
1920
+ /*===========================================================*/
1921
+
1922
+ if (expr2 == NULL) return(expr1);
1923
+
1924
+ /*============================================================*/
1925
+ /* If the 1st expression is an "and" expression, and the 2nd */
1926
+ /* expression is not an "and" expression, then include the */
1927
+ /* 2nd expression in the argument list of the 1st expression. */
1928
+ /*============================================================*/
1929
+
1930
+ if ((expr1->value == ExpressionData(theEnv)->PTR_AND) &&
1931
+ (expr2->value != ExpressionData(theEnv)->PTR_AND))
1932
+ {
1933
+ tempPtr = expr1->bottom;
1934
+ if (tempPtr == NULL)
1935
+ {
1936
+ rtn_struct(theEnv,lhsParseNode,expr1);
1937
+ return(expr2);
1938
+ }
1939
+
1940
+ while (tempPtr->right != NULL)
1941
+ { tempPtr = tempPtr->right; }
1942
+
1943
+ tempPtr->right = expr2;
1944
+ return(expr1);
1945
+ }
1946
+
1947
+ /*============================================================*/
1948
+ /* If the 2nd expression is an "and" expression, and the 1st */
1949
+ /* expression is not an "and" expression, then include the */
1950
+ /* 1st expression in the argument list of the 2nd expression. */
1951
+ /*============================================================*/
1952
+
1953
+ if ((expr1->value != ExpressionData(theEnv)->PTR_AND) &&
1954
+ (expr2->value == ExpressionData(theEnv)->PTR_AND))
1955
+ {
1956
+ tempPtr = expr2->bottom;
1957
+ if (tempPtr == NULL)
1958
+ {
1959
+ rtn_struct(theEnv,lhsParseNode,expr2);
1960
+ return(expr1);
1961
+ }
1962
+
1963
+ expr2->bottom = expr1;
1964
+ expr1->right = tempPtr;
1965
+
1966
+ return(expr2);
1967
+ }
1968
+
1969
+ /*===========================================================*/
1970
+ /* If both expressions are "and" expressions, then add the */
1971
+ /* 2nd expression to the argument list of the 1st expression */
1972
+ /* and throw away the extraneous "and" expression. */
1973
+ /*===========================================================*/
1974
+
1975
+ if ((expr1->value == ExpressionData(theEnv)->PTR_AND) &&
1976
+ (expr2->value == ExpressionData(theEnv)->PTR_AND))
1977
+ {
1978
+ tempPtr = expr1->bottom;
1979
+ if (tempPtr == NULL)
1980
+ {
1981
+ rtn_struct(theEnv,lhsParseNode,expr1);
1982
+ return(expr2);
1983
+ }
1984
+
1985
+ while (tempPtr->right != NULL)
1986
+ { tempPtr = tempPtr->right; }
1987
+
1988
+ tempPtr->right = expr2->bottom;
1989
+ rtn_struct(theEnv,lhsParseNode,expr2);
1990
+
1991
+ return(expr1);
1992
+ }
1993
+
1994
+ /*=====================================================*/
1995
+ /* If neither expression is an "and" expression, then */
1996
+ /* create an "and" expression and add both expressions */
1997
+ /* to the argument list of that "and" expression. */
1998
+ /*=====================================================*/
1999
+
2000
+ tempPtr = GetLHSParseNode(theEnv);
2001
+ tempPtr->pnType = FCALL_NODE;
2002
+ tempPtr->value = ExpressionData(theEnv)->PTR_AND;
2003
+
2004
+ tempPtr->bottom = expr1;
2005
+ expr1->right = expr2;
2006
+ return(tempPtr);
2007
+ }
2008
+
2009
+ /**********************************************/
2010
+ /* PrintNodes: Debugging routine which prints */
2011
+ /* the representation of a CE. */
2012
+ /**********************************************/
2013
+ /*
2014
+ static void PrintNodes(
2015
+ Environment *theEnv,
2016
+ const char *fileid,
2017
+ struct lhsParseNode *theNode)
2018
+ {
2019
+ if (theNode == NULL) return;
2020
+
2021
+ while (theNode != NULL)
2022
+ {
2023
+ switch (theNode->type)
2024
+ {
2025
+ case PATTERN_CE:
2026
+ WriteString(theEnv,fileid,"(");
2027
+ if (theNode->negated) WriteString(theEnv,fileid,"n");
2028
+ if (theNode->exists) WriteString(theEnv,fileid,"x");
2029
+ if (theNode->logical) WriteString(theEnv,fileid,"l");
2030
+ PrintUnsignedInteger(theEnv,fileid,theNode->beginNandDepth);
2031
+ WriteString(theEnv,fileid,"-");
2032
+ PrintUnsignedInteger(theEnv,fileid,theNode->endNandDepth);
2033
+ WriteString(theEnv,fileid," ");
2034
+ WriteString(theEnv,fileid,ValueToString(theNode->right->bottom->value));
2035
+ WriteString(theEnv,fileid,")");
2036
+ break;
2037
+
2038
+ case TEST_CE:
2039
+ WriteString(theEnv,fileid,"(test ");
2040
+ PrintUnsignedInteger(theEnv,fileid,theNode->beginNandDepth);
2041
+ WriteString(theEnv,fileid,"-");
2042
+ PrintUnsignedInteger(theEnv,fileid,theNode->endNandDepth);
2043
+ WriteString(theEnv,fileid,")");
2044
+ break;
2045
+
2046
+ case NOT_CE:
2047
+ if (theNode->logical) WriteString(theEnv,fileid,"(lnot ");
2048
+ else WriteString(theEnv,fileid,"(not ");;
2049
+ PrintNodes(theEnv,fileid,theNode->right);
2050
+ WriteString(theEnv,fileid,")");
2051
+ break;
2052
+
2053
+ case OR_CE:
2054
+ if (theNode->logical) WriteString(theEnv,fileid,"(lor ");
2055
+ else WriteString(theEnv,fileid,"(or ");
2056
+ PrintNodes(theEnv,fileid,theNode->right);
2057
+ WriteString(theEnv,fileid,")");
2058
+ break;
2059
+
2060
+ case AND_CE:
2061
+ if (theNode->logical) WriteString(theEnv,fileid,"(land ");
2062
+ else WriteString(theEnv,fileid,"(and ");
2063
+ PrintNodes(theEnv,fileid,theNode->right);
2064
+ WriteString(theEnv,fileid,")");
2065
+ break;
2066
+
2067
+ default:
2068
+ WriteString(theEnv,fileid,"(unknown)");
2069
+ break;
2070
+
2071
+ }
2072
+
2073
+ theNode = theNode->bottom;
2074
+ if (theNode != NULL) WriteString(theEnv,fileid," ");
2075
+ }
2076
+
2077
+ return;
2078
+ }
2079
+ */
2080
+
2081
+ #endif
2082
+