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