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