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