tl_rewrt.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /***** tl_spin: tl_rewrt.c *****/
  10. /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
  11. /* All Rights Reserved. This software is for educational purposes only. */
  12. /* No guarantee whatsoever is expressed or implied by the distribution of */
  13. /* this code. Permission is given to distribute this code provided that */
  14. /* this introductory message is not removed and no monies are exchanged. */
  15. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  16. /* http://spinroot.com/ */
  17. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  18. /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
  19. /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
  20. #include "tl.h"
  21. extern int tl_verbose;
  22. static Node *can = ZN;
  23. void
  24. ini_rewrt(void)
  25. {
  26. can = ZN;
  27. }
  28. Node *
  29. right_linked(Node *n)
  30. {
  31. if (!n) return n;
  32. if (n->ntyp == AND || n->ntyp == OR)
  33. while (n->lft && n->lft->ntyp == n->ntyp)
  34. { Node *tmp = n->lft;
  35. n->lft = tmp->rgt;
  36. tmp->rgt = n;
  37. n = tmp;
  38. }
  39. n->lft = right_linked(n->lft);
  40. n->rgt = right_linked(n->rgt);
  41. return n;
  42. }
  43. Node *
  44. canonical(Node *n)
  45. { Node *m; /* assumes input is right_linked */
  46. if (!n) return n;
  47. if ((m = in_cache(n)) != ZN)
  48. return m;
  49. n->rgt = canonical(n->rgt);
  50. n->lft = canonical(n->lft);
  51. return cached(n);
  52. }
  53. Node *
  54. push_negation(Node *n)
  55. { Node *m;
  56. Assert(n->ntyp == NOT, n->ntyp);
  57. switch (n->lft->ntyp) {
  58. case TRUE:
  59. Debug("!true => false\n");
  60. releasenode(0, n->lft);
  61. n->lft = ZN;
  62. n->ntyp = FALSE;
  63. break;
  64. case FALSE:
  65. Debug("!false => true\n");
  66. releasenode(0, n->lft);
  67. n->lft = ZN;
  68. n->ntyp = TRUE;
  69. break;
  70. case NOT:
  71. Debug("!!p => p\n");
  72. m = n->lft->lft;
  73. releasenode(0, n->lft);
  74. n->lft = ZN;
  75. releasenode(0, n);
  76. n = m;
  77. break;
  78. case V_OPER:
  79. Debug("!(p V q) => (!p U !q)\n");
  80. n->ntyp = U_OPER;
  81. goto same;
  82. case U_OPER:
  83. Debug("!(p U q) => (!p V !q)\n");
  84. n->ntyp = V_OPER;
  85. goto same;
  86. #ifdef NXT
  87. case NEXT:
  88. Debug("!X -> X!\n");
  89. n->ntyp = NEXT;
  90. n->lft->ntyp = NOT;
  91. n->lft = push_negation(n->lft);
  92. break;
  93. #endif
  94. case AND:
  95. Debug("!(p && q) => !p || !q\n");
  96. n->ntyp = OR;
  97. goto same;
  98. case OR:
  99. Debug("!(p || q) => !p && !q\n");
  100. n->ntyp = AND;
  101. same: m = n->lft->rgt;
  102. n->lft->rgt = ZN;
  103. n->rgt = Not(m);
  104. n->lft->ntyp = NOT;
  105. m = n->lft;
  106. n->lft = push_negation(m);
  107. break;
  108. }
  109. return rewrite(n);
  110. }
  111. static void
  112. addcan(int tok, Node *n)
  113. { Node *m, *prev = ZN;
  114. Node **ptr;
  115. Node *N;
  116. Symbol *s, *t; int cmp;
  117. if (!n) return;
  118. if (n->ntyp == tok)
  119. { addcan(tok, n->rgt);
  120. addcan(tok, n->lft);
  121. return;
  122. }
  123. N = dupnode(n);
  124. if (!can)
  125. { can = N;
  126. return;
  127. }
  128. s = DoDump(N);
  129. if (can->ntyp != tok) /* only one element in list so far */
  130. { ptr = &can;
  131. goto insert;
  132. }
  133. /* there are at least 2 elements in list */
  134. prev = ZN;
  135. for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt)
  136. { t = DoDump(m->lft);
  137. if (t != ZS)
  138. cmp = strcmp(s->name, t->name);
  139. else
  140. cmp = 0;
  141. if (cmp == 0) /* duplicate */
  142. return;
  143. if (cmp < 0)
  144. { if (!prev)
  145. { can = tl_nn(tok, N, can);
  146. return;
  147. } else
  148. { ptr = &(prev->rgt);
  149. goto insert;
  150. } } }
  151. /* new entry goes at the end of the list */
  152. ptr = &(prev->rgt);
  153. insert:
  154. t = DoDump(*ptr);
  155. cmp = strcmp(s->name, t->name);
  156. if (cmp == 0) /* duplicate */
  157. return;
  158. if (cmp < 0)
  159. *ptr = tl_nn(tok, N, *ptr);
  160. else
  161. *ptr = tl_nn(tok, *ptr, N);
  162. }
  163. static void
  164. marknode(int tok, Node *m)
  165. {
  166. if (m->ntyp != tok)
  167. { releasenode(0, m->rgt);
  168. m->rgt = ZN;
  169. }
  170. m->ntyp = -1;
  171. }
  172. Node *
  173. Canonical(Node *n)
  174. { Node *m, *p, *k1, *k2, *prev, *dflt = ZN;
  175. int tok;
  176. if (!n) return n;
  177. tok = n->ntyp;
  178. if (tok != AND && tok != OR)
  179. return n;
  180. can = ZN;
  181. addcan(tok, n);
  182. #if 0
  183. Debug("\nA0: "); Dump(can);
  184. Debug("\nA1: "); Dump(n); Debug("\n");
  185. #endif
  186. releasenode(1, n);
  187. /* mark redundant nodes */
  188. if (tok == AND)
  189. { for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
  190. { k1 = (m->ntyp == AND) ? m->lft : m;
  191. if (k1->ntyp == TRUE)
  192. { marknode(AND, m);
  193. dflt = True;
  194. continue;
  195. }
  196. if (k1->ntyp == FALSE)
  197. { releasenode(1, can);
  198. can = False;
  199. goto out;
  200. } }
  201. for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
  202. for (p = can; p; p = (p->ntyp == AND) ? p->rgt : ZN)
  203. { if (p == m
  204. || p->ntyp == -1
  205. || m->ntyp == -1)
  206. continue;
  207. k1 = (m->ntyp == AND) ? m->lft : m;
  208. k2 = (p->ntyp == AND) ? p->lft : p;
  209. if (isequal(k1, k2))
  210. { marknode(AND, p);
  211. continue;
  212. }
  213. if (anywhere(OR, k1, k2))
  214. { marknode(AND, p);
  215. continue;
  216. }
  217. } }
  218. if (tok == OR)
  219. { for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
  220. { k1 = (m->ntyp == OR) ? m->lft : m;
  221. if (k1->ntyp == FALSE)
  222. { marknode(OR, m);
  223. dflt = False;
  224. continue;
  225. }
  226. if (k1->ntyp == TRUE)
  227. { releasenode(1, can);
  228. can = True;
  229. goto out;
  230. } }
  231. for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
  232. for (p = can; p; p = (p->ntyp == OR) ? p->rgt : ZN)
  233. { if (p == m
  234. || p->ntyp == -1
  235. || m->ntyp == -1)
  236. continue;
  237. k1 = (m->ntyp == OR) ? m->lft : m;
  238. k2 = (p->ntyp == OR) ? p->lft : p;
  239. if (isequal(k1, k2))
  240. { marknode(OR, p);
  241. continue;
  242. }
  243. if (anywhere(AND, k1, k2))
  244. { marknode(OR, p);
  245. continue;
  246. }
  247. } }
  248. for (m = can, prev = ZN; m; ) /* remove marked nodes */
  249. { if (m->ntyp == -1)
  250. { k2 = m->rgt;
  251. releasenode(0, m);
  252. if (!prev)
  253. { m = can = can->rgt;
  254. } else
  255. { m = prev->rgt = k2;
  256. /* if deleted the last node in a chain */
  257. if (!prev->rgt && prev->lft
  258. && (prev->ntyp == AND || prev->ntyp == OR))
  259. { k1 = prev->lft;
  260. prev->ntyp = prev->lft->ntyp;
  261. prev->sym = prev->lft->sym;
  262. prev->rgt = prev->lft->rgt;
  263. prev->lft = prev->lft->lft;
  264. releasenode(0, k1);
  265. }
  266. }
  267. continue;
  268. }
  269. prev = m;
  270. m = m->rgt;
  271. }
  272. out:
  273. #if 0
  274. Debug("A2: "); Dump(can); Debug("\n");
  275. #endif
  276. if (!can)
  277. { if (!dflt)
  278. fatal("cannot happen, Canonical", (char *) 0);
  279. return dflt;
  280. }
  281. return can;
  282. }