Add SCFence analysis
[model-checker.git] / scfence / inferlist.cc
1 #include "inferlist.h"
2
3 InferenceList::InferenceList() {
4         list = new ModelList<Inference*>;
5 }
6
7 int InferenceList::getSize() {
8         return list->size();
9 }
10
11 void InferenceList::pop_back() {
12         list->pop_back();
13 }
14
15 Inference* InferenceList::back() {
16         return list->back();
17 }
18
19 void InferenceList::push_back(Inference *infer) {
20         list->push_back(infer);
21 }
22
23 void InferenceList::pop_front() {
24         list->pop_front();
25 }
26
27 /** We should not call this function too often because we want a nicer
28  *  abstraction of the list of inferences. So far, it will only be called in
29  *  the functions in InferenceSet */
30 ModelList<Inference*>* InferenceList::getList() {
31         return list;
32 }
33
34 bool InferenceList::applyPatch(Inference *curInfer, Inference *newInfer, Patch *patch) {
35         bool canUpdate = true,
36                 hasUpdated = false,
37                 updateState = false;
38         for (int i = 0; i < patch->getSize(); i++) {
39                 canUpdate = true;
40                 hasUpdated = false;
41                 PatchUnit *unit = patch->get(i);
42                 newInfer->strengthen(unit->getAct(), unit->getMO(), canUpdate, hasUpdated);
43                 if (!canUpdate) {
44                         // This is not a feasible patch, bail
45                         break;
46                 } else if (hasUpdated) {
47                         updateState = true;
48                 }
49         }
50         if (updateState) {
51                 return true;
52         } else {
53                 return false;
54         }
55 }
56
57 void InferenceList::applyPatch(Inference *curInfer, Patch* patch) {
58         if (list->empty()) {
59                 Inference *newInfer = new Inference(curInfer);
60                 if (!applyPatch(curInfer, newInfer, patch)) {
61                         delete newInfer;
62                 } else {
63                         list->push_back(newInfer);
64                 }
65         } else {
66                 ModelList<Inference*> *newList = new ModelList<Inference*>;
67                 for (ModelList<Inference*>::iterator it = list->begin(); it !=
68                         list->end(); it++) {
69                         Inference *oldInfer = *it;
70                         Inference *newInfer = new Inference(oldInfer);
71                         if (!applyPatch(curInfer, newInfer, patch)) {
72                                 delete newInfer;
73                         } else {
74                                 newList->push_back(newInfer);
75                         }
76                 }
77                 // Clean the old list
78                 for (ModelList<Inference*>::iterator it = list->begin(); it !=
79                         list->end(); it++) {
80                         delete *it;
81                 }
82                 delete list;
83                 list = newList;
84         }       
85 }
86
87 void InferenceList::applyPatch(Inference *curInfer, SnapVector<Patch*> *patches) {
88         if (list->empty()) {
89                 for (unsigned i = 0; i < patches->size(); i++) {
90                         Inference *newInfer = new Inference(curInfer);
91                         Patch *patch = (*patches)[i];
92                         if (!applyPatch(curInfer, newInfer, patch)) {
93                                 delete newInfer;
94                         } else {
95                                 list->push_back(newInfer);
96                         }
97                 }
98         } else {
99                 ModelList<Inference*> *newList = new ModelList<Inference*>;
100                 for (ModelList<Inference*>::iterator it = list->begin(); it !=
101                         list->end(); it++) {
102                         Inference *oldInfer = *it;
103                         for (unsigned i = 0; i < patches->size(); i++) {
104                                 Inference *newInfer = new Inference(oldInfer);
105                                 Patch *patch = (*patches)[i];
106                                 if (!applyPatch(curInfer, newInfer, patch)) {
107                                         delete newInfer;
108                                 } else {
109                                         newList->push_back(newInfer);
110                                 }
111                         }
112                 }
113                 // Clean the old list
114                 for (ModelList<Inference*>::iterator it = list->begin(); it !=
115                         list->end(); it++) {
116                         delete *it;
117                 }
118                 delete list;
119                 list = newList;
120         }
121 }
122
123 /** Append another list to this list */
124 bool InferenceList::append(InferenceList *inferList) {
125         if (!inferList)
126                 return false;
127         ModelList<Inference*> *l = inferList->list;
128         list->insert(list->end(), l->begin(), l->end());
129         return true;
130 }
131
132 /** Only choose the weakest existing candidates & they must be stronger than the
133  * current inference */
134 void InferenceList::pruneCandidates(Inference *curInfer) {
135         ModelList<Inference*> *newCandidates = new ModelList<Inference*>(),
136                 *candidates = list;
137
138         ModelList<Inference*>::iterator it1, it2;
139         int compVal;
140         for (it1 = candidates->begin(); it1 != candidates->end(); it1++) {
141                 Inference *cand = *it1;
142                 compVal = cand->compareTo(curInfer);
143                 if (compVal == 0) {
144                         // If as strong as curInfer, bail
145                         delete cand;
146                         continue;
147                 }
148                 // Check if the cand is any stronger than those in the newCandidates
149                 for (it2 = newCandidates->begin(); it2 != newCandidates->end(); it2++) {
150                         Inference *addedInfer = *it2;
151                         compVal = addedInfer->compareTo(cand);
152                         if (compVal == 0 || compVal == 1) { // Added inference is stronger
153                                 delete addedInfer;
154                                 it2 = newCandidates->erase(it2);
155                                 it2--;
156                         }
157                 }
158                 // Now push the cand to the list
159                 newCandidates->push_back(cand);
160         }
161         delete candidates;
162         list = newCandidates;
163 }
164
165 void InferenceList::clearAll() {
166         clearAll(list);
167 }
168
169 void InferenceList::clearList() {
170         delete list;
171 }
172
173 void InferenceList::clearAll(ModelList<Inference*> *l) {
174         for (ModelList<Inference*>::iterator it = l->begin(); it !=
175                 l->end(); it++) {
176                 Inference *infer = *it;
177                 delete infer;
178         }
179         delete l;
180 }
181
182 void InferenceList::clearAll(InferenceList *inferList) {
183         clearAll(inferList->list);
184 }
185
186 void InferenceList::print(InferenceList *inferList, const char *msg) {
187         print(inferList->getList(), msg);
188 }
189
190 void InferenceList::print(ModelList<Inference*> *inferList, const char *msg) {
191         for (ModelList<Inference*>::iterator it = inferList->begin(); it !=
192                 inferList->end(); it++) {
193                 int idx = distance(inferList->begin(), it);
194                 Inference *infer = *it;
195                 model_print("%s %d:\n", msg, idx);
196                 infer->print();
197                 model_print("\n");
198         }
199 }
200
201 void InferenceList::print() {
202         print(list, "Inference");
203 }
204
205 void InferenceList::print(const char *msg) {
206         print(list, msg);
207 }