tl_rewrt.c 6.1 KB

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