1 /***** tl_spin: tl_rewrt.c *****/
3 /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
4 /* All Rights Reserved. This software is for educational purposes only. */
5 /* No guarantee whatsoever is expressed or implied by the distribution of */
6 /* this code. Permission is given to distribute this code provided that */
7 /* this introductory message is not removed and no monies are exchanged. */
8 /* Software written by Gerard J. Holzmann. For tool documentation see: */
9 /* http://spinroot.com/ */
10 /* Send all bug-reports and/or questions to: bugs@spinroot.com */
12 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
13 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
17 extern int tl_verbose;
19 static Node *can = ZN;
26 if (n->ntyp == AND || n->ntyp == OR)
27 while (n->lft && n->lft->ntyp == n->ntyp)
34 n->lft = right_linked(n->lft);
35 n->rgt = right_linked(n->rgt);
42 { Node *m; /* assumes input is right_linked */
45 if ((m = in_cache(n)) != ZN)
48 n->rgt = canonical(n->rgt);
49 n->lft = canonical(n->lft);
55 push_negation(Node *n)
58 Assert(n->ntyp == NOT, n->ntyp);
60 switch (n->lft->ntyp) {
62 Debug("!true => false\n");
63 releasenode(0, n->lft);
68 Debug("!false => true\n");
69 releasenode(0, n->lft);
76 releasenode(0, n->lft);
82 Debug("!(p V q) => (!p U !q)\n");
86 Debug("!(p U q) => (!p V !q)\n");
94 n->lft = push_negation(n->lft);
98 Debug("!(p && q) => !p || !q\n");
102 Debug("!(p || q) => !p && !q\n");
105 same: m = n->lft->rgt;
111 n->lft = push_negation(m);
119 addcan(int tok, Node *n)
120 { Node *m, *prev = ZN;
123 Symbol *s, *t; int cmp;
128 { addcan(tok, n->rgt);
140 if (can->ntyp != tok) /* only one element in list so far */
145 /* there are at least 2 elements in list */
147 for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt)
148 { t = DoDump(m->lft);
149 cmp = strcmp(s->name, t->name);
150 if (cmp == 0) /* duplicate */
154 { can = tl_nn(tok, N, can);
157 { ptr = &(prev->rgt);
161 /* new entry goes at the end of the list */
165 cmp = strcmp(s->name, t->name);
166 if (cmp == 0) /* duplicate */
169 *ptr = tl_nn(tok, N, *ptr);
171 *ptr = tl_nn(tok, *ptr, N);
175 marknode(int tok, Node *m)
178 { releasenode(0, m->rgt);
186 { Node *m, *p, *k1, *k2, *prev, *dflt = ZN;
192 if (tok != AND && tok != OR)
198 Debug("\nA0: "); Dump(can);
199 Debug("\nA1: "); Dump(n); Debug("\n");
203 /* mark redundant nodes */
205 { for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
206 { k1 = (m->ntyp == AND) ? m->lft : m;
207 if (k1->ntyp == TRUE)
212 if (k1->ntyp == FALSE)
213 { releasenode(1, can);
217 for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
218 for (p = can; p; p = (p->ntyp == AND) ? p->rgt : ZN)
223 k1 = (m->ntyp == AND) ? m->lft : m;
224 k2 = (p->ntyp == AND) ? p->lft : p;
230 if (anywhere(OR, k1, k2))
236 { for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
237 { k1 = (m->ntyp == OR) ? m->lft : m;
238 if (k1->ntyp == FALSE)
243 if (k1->ntyp == TRUE)
244 { releasenode(1, can);
248 for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
249 for (p = can; p; p = (p->ntyp == OR) ? p->rgt : ZN)
254 k1 = (m->ntyp == OR) ? m->lft : m;
255 k2 = (p->ntyp == OR) ? p->lft : p;
261 if (anywhere(AND, k1, k2))
266 for (m = can, prev = ZN; m; ) /* remove marked nodes */
271 { m = can = can->rgt;
273 { m = prev->rgt = k2;
274 /* if deleted the last node in a chain */
275 if (!prev->rgt && prev->lft
276 && (prev->ntyp == AND || prev->ntyp == OR))
278 prev->ntyp = prev->lft->ntyp;
279 prev->sym = prev->lft->sym;
280 prev->rgt = prev->lft->rgt;
281 prev->lft = prev->lft->lft;
292 Debug("A2: "); Dump(can); Debug("\n");
296 fatal("cannot happen, Canonical", (char *) 0);