Added support to printout data structure update nodes (bindings/updates)
[repair.git] / Repair / RepairCompiler / MCC / IR / OpExpr.java
1 package MCC.IR;
2
3 import java.util.*;
4
5 public class OpExpr extends Expr {
6
7     Expr left;
8     Expr right;
9     Opcode opcode;
10
11     public OpExpr(Opcode opcode, Expr left, Expr right) {
12         this.opcode = opcode;
13         this.left = left;
14         this.right = right;
15
16         assert (right == null && opcode == Opcode.NOT) || (right != null);
17     }
18
19     public Expr getRightExpr() {
20         return right;
21     }
22
23     public Expr getLeftExpr() {
24         return left;
25     }
26
27     public Set freeVars() {
28         Set lset=left.freeVars();
29         Set rset=null;
30         if (right!=null)
31             rset=right.freeVars();
32         if (lset==null)
33             return rset;
34         if (rset!=null)
35             lset.addAll(rset);
36         return lset;
37     }
38
39     public String name() {
40         if (opcode==Opcode.NOT)
41             return "!("+left.name()+")";
42         String name=left.name()+opcode.toString();
43         if (right!=null)
44             name+=right.name();
45         return name;
46     }
47
48     public Opcode getOpcode() {
49         return opcode;
50     }
51
52
53
54
55     public boolean equals(Map remap, Expr e) {
56         if (e==null||!(e instanceof OpExpr))
57             return false;
58         OpExpr oe=(OpExpr)e;
59         if (opcode!=oe.opcode)
60             return false;
61         if (!left.equals(remap,oe.left))
62             return false;
63         if (opcode!=Opcode.NOT)
64             if (!right.equals(remap,oe.right))
65                 return false;
66         return true;
67     }
68
69     public DNFRule constructDNF() {
70         if (opcode==Opcode.AND) {
71             DNFRule leftd=left.constructDNF();
72             DNFRule rightd=right.constructDNF();
73             return leftd.and(rightd);
74         } else if (opcode==Opcode.OR) {
75             DNFRule leftd=left.constructDNF();
76             DNFRule rightd=right.constructDNF();
77             return leftd.or(rightd);
78         } else if (opcode==Opcode.NOT) {
79             DNFRule leftd=left.constructDNF();
80             return leftd.not();
81         } else return new DNFRule(this);
82     }
83
84     public boolean usesDescriptor(Descriptor d) {
85         if (opcode==Opcode.GT||opcode==Opcode.GE||opcode==Opcode.LT||
86             opcode==Opcode.LE||opcode==Opcode.EQ||opcode==Opcode.NE)
87             return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
88             //      return right.usesDescriptor(d);
89         else
90             return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
91     }
92     
93
94     public int[] getRepairs(boolean negated) {
95         if (left instanceof RelationExpr)
96             return new int[] {AbstractRepair.MODIFYRELATION};
97         if (left instanceof SizeofExpr) {
98             boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
99             if (isRelation) {
100                 if (opcode==Opcode.EQ)
101                     if (((IntegerLiteralExpr)right).getValue()==0)
102                         return new int[] {AbstractRepair.REMOVEFROMRELATION};
103                     else
104                         return new int[] {AbstractRepair.ADDTORELATION,
105                                               AbstractRepair.REMOVEFROMRELATION};
106                 if (((opcode==Opcode.GE)&&!negated)||
107                     ((opcode==Opcode.LE)&&negated)) {
108                     if (((IntegerLiteralExpr)right).getValue()==0)
109                         return new int[0];
110                     else
111                         return new int[]{AbstractRepair.ADDTORELATION}; }
112                 else
113                     return new int[]{AbstractRepair.REMOVEFROMRELATION};
114             } else {
115                 if (opcode==Opcode.EQ)
116                     if (((IntegerLiteralExpr)right).getValue()==0)
117                         return new int[] {AbstractRepair.REMOVEFROMSET};                        
118                     else
119                         return new int[] {AbstractRepair.ADDTOSET,
120                                               AbstractRepair.REMOVEFROMSET};
121                 
122                 if (((opcode==Opcode.GE)&&!negated)||
123                     ((opcode==Opcode.LE)&&negated)) {
124                     if (((IntegerLiteralExpr)right).getValue()==0)
125                         return new int[0];
126                     else
127                         return new int[] {AbstractRepair.ADDTOSET}; }
128                 else
129                     return new int[] {AbstractRepair.REMOVEFROMSET};
130             }
131         }
132         throw new Error("BAD");
133     }
134     
135     public Descriptor getDescriptor() {
136         return left.getDescriptor();
137     }
138
139     public boolean inverted() {
140         return left.inverted();
141     }
142
143     public Set getInversedRelations() {
144         Set set = left.getInversedRelations();
145         if (right != null) {
146             set.addAll(right.getInversedRelations());
147         }
148         return set;
149     }
150
151     public Set getRequiredDescriptors() {
152         Set v = left.getRequiredDescriptors();
153      
154         if (right != null) {
155             v.addAll(right.getRequiredDescriptors());
156         }
157
158         return v;
159     }   
160
161     public void generate(CodeWriter writer, VarDescriptor dest) {
162         VarDescriptor ld = VarDescriptor.makeNew("leftop");
163         left.generate(writer, ld);        
164         VarDescriptor rd = null;
165
166         if (right != null) {
167             rd = VarDescriptor.makeNew("rightop");
168             right.generate(writer, rd);
169         }
170
171         String code;
172         if (opcode != Opcode.NOT) { /* two operands */
173             assert rd != null;
174             writer.outputline("int " + dest.getSafeSymbol() + " = " + 
175                               ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
176         } else {
177             writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
178         }
179     }
180
181     public void prettyPrint(PrettyPrinter pp) {
182         pp.output("(");
183         if (opcode == Opcode.NOT) {
184             left.prettyPrint(pp);
185         } else {           
186             left.prettyPrint(pp);
187             pp.output(" " + opcode.toString() + " ");
188             assert right != null;
189             right.prettyPrint(pp);
190         }
191         pp.output(")");
192     }
193
194     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
195         TypeDescriptor lt = left.typecheck(sa);
196         TypeDescriptor rt = right == null ? null : right.typecheck(sa);
197
198         if (lt == null) {
199             return null;
200         } else if (right != null && rt == null) {
201             return null;
202         }
203
204         boolean ok = true;
205
206         // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
207         // either that or we use a isvalid clause to check for null
208
209         /*
210         if (lt != ReservedTypeDescriptor.INT) {
211             sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
212             ok = false;
213         }
214
215         if (right != null) {
216             if (rt != ReservedTypeDescriptor.INT) {
217                 sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
218                 ok = false;
219             }
220         }
221         */
222
223         if (!ok) {
224             return null;
225         }
226
227         this.td = ReservedTypeDescriptor.INT;
228         return this.td;
229     }
230
231 }
232
233
234
235
236