Hack grammar to add unary minus.
[repair.git] / Repair / RepairInterpreter / fieldcheck.cc
1 #include <stdlib.h>
2 #include "classlist.h"
3 #include "fieldcheck.h"
4 #include "common.h"
5 #include "set.h"
6 #include "dmodel.h"
7 #include "omodel.h"
8 #include "model.h"
9 #include "Hashtable.h"
10 #include "normalizer.h"
11
12 FieldCheck::FieldCheck(model *m) {
13   cptoreqs=NULL;
14   nftoprovides=NULL;
15   globalmodel=m;
16   propertytonf=NULL;
17 }
18
19 bool FieldCheck::testsatisfy(WorkSet *satisfies, FieldTuple *ft) {
20   FieldTuple *copy=new FieldTuple(ft);
21   bool sat=false;
22   while(!sat&&copy!=NULL) {
23     if(satisfies->contains(copy)) {
24       sat=true;
25       break;
26     }
27     copy->set=globalmodel->getdomainrelation()->getsuperset(globalmodel->getdomainrelation()->getset(copy->set))->getname();
28   }
29   delete(copy);
30   return sat;
31 }
32
33 int FieldCheck::getindexthatprovides(char *set, char *relation) {
34   FieldTuple *copy=new FieldTuple(set,relation);
35   while(copy!=NULL) {
36     if(propertytonf->contains(copy)) {
37       /* Found!!! Do stuff */
38       NormalForm *nf=(NormalForm *)propertytonf->get(copy);
39       for(int i=0;i<globalmodel->getnumconstraints();i++) {
40         if (nf==globalmodel->getnormalform(i)) {
41           delete(copy);
42           return i;
43         }
44       }
45       printf("Error in getindexthatprovides\n");
46       exit(-1);
47     }
48     copy->set=globalmodel->getdomainrelation()->getsuperset(globalmodel->getdomainrelation()->getset(copy->set))->getname();
49   }
50   delete(copy);
51   return -1; /* Couldn't find...too bad */
52 }
53
54 void FieldCheck::analyze() {
55   WorkSet *satisfied=new WorkSet();
56   propertytonf=new Hashtable(NULL,NULL);
57   bool change=true;
58   bool allsatisfied=true;
59   FieldTuple *badft=NULL;
60   while(change) {
61     allsatisfied=true;
62     change=false;
63     for(int i=0;i<globalmodel->getnumconstraints();i++) {
64       NormalForm *nf=globalmodel->getnormalform(i);
65       bool gotallreqs=true;
66       for(int j=0;j<nf->getnumsentences();j++) {
67         CoerceSentence *cs=nf->getsentence(j);
68         for (int k=0;k<cs->getnumpredicates();k++) {
69           CoercePredicate *cp=cs->getpredicate(k);
70           WorkSet *reqs=(WorkSet *)cptoreqs->get(cp);
71           if (reqs!=NULL) {
72             for(FieldTuple *ft=(FieldTuple *)reqs->firstelement();ft!=NULL;
73                 ft=(FieldTuple*)reqs->getnextelement(ft)) {
74               if (!testsatisfy(satisfied,ft)) {
75                 gotallreqs=false;
76                 allsatisfied=false;
77                 badft=ft;
78                 break;
79               }
80             }
81           }
82           if(!gotallreqs)
83             break;
84         }
85         if (gotallreqs) {
86           WorkSet *provides=(WorkSet *)nftoprovides->get(nf);
87           if(provides!=NULL) {
88             for(FieldTuple *ft=(FieldTuple *)provides->firstelement();ft!=NULL;
89                 ft=(FieldTuple*)provides->getnextelement(ft)) {
90               if(!testsatisfy(satisfied,ft)) {
91                 /* something to add */
92                 satisfied->addobject(ft);
93                 propertytonf->put(ft,nf);
94                 change=true;
95               }
96             }
97           }
98         }
99       }
100     }
101   }
102   if (!allsatisfied) {
103     printf("Some relations can't be established:<%s,%s>",badft->relation,badft->set);
104     exit(-1);
105   }
106   delete(satisfied);
107 }
108
109 void FieldCheck::buildmaps() {
110   cptoreqs=new Hashtable(NULL,NULL);
111   nftoprovides=new Hashtable(NULL,NULL);
112
113   for(int i=0;i<globalmodel->getnumconstraints();i++) {
114     NormalForm *nf=globalmodel->getnormalform(i);
115     Constraint *c=globalmodel->getconstraint(i);
116     WorkSet *old=NULL;
117     for(int j=0;j<nf->getnumsentences();j++) {
118       WorkSet *curr=new WorkSet();
119       CoerceSentence *cs=nf->getsentence(j);
120       for (int k=0;k<cs->getnumpredicates();k++) {
121         CoercePredicate *cp=cs->getpredicate(k);
122         WorkSet *wr=requireswhat(c,cp);
123         if (wr!=NULL)
124           cptoreqs->put(cp,wr);
125         FieldTuple *ft=provideswhat(c,cp);
126         if(ft!=NULL)
127           curr->addobject(ft);
128         else
129           delete(ft);
130       }
131       if (old==NULL)
132         old=curr;
133       else {
134         for(FieldTuple *ft=(FieldTuple *)old->firstelement();ft!=NULL;
135             ft=(FieldTuple *)old->getnextelement(ft)) {
136           if (!curr->contains(ft))
137             old->removeobject(ft);
138         }
139         delete(curr);
140       }
141     }
142     if(old!=NULL) {
143       if(old->isEmpty())
144         delete old;
145       else
146         nftoprovides->put(nf, old);
147     }
148   }
149 }
150
151 WorkSet * FieldCheck::requireswhat(Constraint *c,CoercePredicate *cp) {
152   Predicate *p=cp->getpredicate();
153   int type=p->gettype();
154   if (type==PREDICATE_LT ||
155       type==PREDICATE_LTE ||
156       type==PREDICATE_EQUALS ||
157       type==PREDICATE_GT ||
158       type==PREDICATE_GTE) {
159     WorkSet *ws=new WorkSet();
160     Elementexpr *ee=p->geteleexpr();
161     processee(ws,c,ee);
162     if (ws->isEmpty()) {
163       delete(ws);
164       return NULL;
165     } else return ws;
166   } else return NULL;
167 }
168
169 void FieldCheck::processee(WorkSet *ws, Constraint *c, Elementexpr *ee) {
170   switch(ee->gettype()) {
171   case ELEMENTEXPR_SUB:
172   case ELEMENTEXPR_ADD:
173   case ELEMENTEXPR_MULT:
174     processee(ws,c,ee->getleft());
175     processee(ws,c,ee->getright());
176     return;
177   case ELEMENTEXPR_RELATION: {
178     /* Interesting case */
179     char *rel=ee->getrelation()->getname();
180     Elementexpr *left=ee->getleft();
181     int tleft=left->gettype();
182     if (tleft==ELEMENTEXPR_LABEL) {
183       ws->addobject(new FieldTuple(rel,getset(c, left->getlabel()->label())));
184     } else if (tleft==ELEMENTEXPR_RELATION) {
185       DRelation *drl=globalmodel->getdomainrelation()->getrelation(left->getrelation()->getname());
186       char *rangeofl=drl->getrange();
187       ws->addobject(new FieldTuple(rel,rangeofl));
188     } else {
189       ee->print();
190       printf("Can't determine domain\n");
191       exit(-1);
192     }
193   }
194   return;
195   default:
196     return;
197   }
198 }
199
200 bool FieldCheck::setok(Constraint *c, char *set) {
201   for(int i=0;i<c->numquants();i++) {
202     Quantifier *q=c->getquant(i);
203     char *qs=q->getset()->getname();
204     DomainRelation *dr=globalmodel->getdomainrelation();
205     DomainSet *iset=dr->getset(set);
206     DomainSet *qset=dr->getset(qs);
207     if (dr->issupersetof(iset,qset))
208       return false;
209   }
210   return true;
211 }
212
213 FieldTuple * FieldCheck::provideswhat(Constraint *c,CoercePredicate *cp) {
214   if (cp->getcoercebool())
215     return NULL;
216   Predicate *p=cp->getpredicate();
217   switch(p->gettype()) {
218   case PREDICATE_LT:
219   case PREDICATE_LTE:
220   case PREDICATE_EQUALS:
221   case PREDICATE_GTE:
222   case PREDICATE_GT: {
223     char *relation=p->getvalueexpr()->getrelation()->getname();
224     char *var=p->getvalueexpr()->getlabel()->label();
225     char *set=getset(c,var);
226     if (setok(c,set)) {
227       return new FieldTuple(relation,set);
228     } else
229       return NULL;
230   }
231   case PREDICATE_SET:
232   case PREDICATE_EQ1:
233   case PREDICATE_GTE1: {
234     Setexpr *se=p->getsetexpr();
235     if (se->gettype()==SETEXPR_REL) {
236       char *relation=se->getrelation()->getname();
237       char *var=se->getlabel()->label();
238       char *set=getset(c,var);
239       if (setok(c,set)) {
240         return new FieldTuple(relation,set);
241       } else return NULL;
242     }
243     return NULL;
244   }
245   default:
246     return NULL;
247   }
248 }
249
250 char *getset(Constraint *c, char *var) {
251   for (int i=0;i<c->numquants();i++) {
252     Quantifier *q=c->getquant(i);
253     if (equivalentstrings(var,q->getlabel()->label())) {
254       return q->getset()->getname();
255     }
256   }
257   return NULL;
258 }
259
260 unsigned int FieldTuple::hashCode() {
261   return hashstring(relation)^hashstring(set);
262 }
263
264 bool FieldTuple::equals(ElementWrapper *other) {
265   if (other->type()!=ELEMENT_FTUPLE)
266     return false;
267   FieldTuple *oft=(FieldTuple *)other;
268   if (equivalentstrings(relation, oft->relation)&&
269       equivalentstrings(set,oft->set))
270     return true;
271   else
272     return false;
273 }
274
275 int FieldTuple::type() {
276   return ELEMENT_FTUPLE;
277 }
278
279 FieldTuple::FieldTuple(char * r, char *s) {
280   relation=r;
281   set=s;
282 }
283
284 FieldTuple::FieldTuple(FieldTuple *o) {
285   this->relation=o->relation;
286   this->set=o->set;
287 }