tl_rewrt.c 5.8 KB

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