5 public class OpExpr extends Expr {
11 public static boolean isInt(Expr e) {
12 if ((e instanceof IntegerLiteralExpr)||
13 ((e instanceof OpExpr)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
18 public static int getInt(Expr e) {
19 if (e instanceof IntegerLiteralExpr)
20 return ((IntegerLiteralExpr)e).getValue();
21 else if ((e instanceof OpExpr) && (((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr))
22 return ((IntegerLiteralExpr)((OpExpr)e).getLeftExpr()).getValue();
23 else throw new Error();
26 public OpExpr(Opcode opcode, Expr left, Expr right) {
27 if ((isInt(left)&&isInt(right))||
28 (isInt(left)&&(opcode==Opcode.NOT))||
29 (isInt(left)&&(opcode==Opcode.RND))) {
30 this.opcode=Opcode.NOP;
32 int lint=getInt(left);
33 int rint=getInt(right);
35 if (opcode==Opcode.ADD) {
37 } else if (opcode==Opcode.SUB) {
39 } else if (opcode==Opcode.SHL) {
41 } else if (opcode==Opcode.SHR) {
43 } else if (opcode==Opcode.MULT) {
45 } else if (opcode==Opcode.DIV) {
47 } else if (opcode==Opcode.GT) {
50 } else if (opcode==Opcode.GE) {
53 } else if (opcode==Opcode.LT) {
56 } else if (opcode==Opcode.LE) {
59 } else if (opcode==Opcode.EQ) {
62 } else if (opcode==Opcode.NE) {
65 } else if (opcode==Opcode.AND) {
66 if ((lint!=0)&&(rint!=0))
68 } else if (opcode==Opcode.OR) {
69 if ((lint!=0)||(rint!=0))
71 } else if (opcode==Opcode.NOT) {
74 } else if (opcode==Opcode.RND) {
78 } else throw new Error("Unrecognized Opcode");
79 this.left=new IntegerLiteralExpr(value);
84 assert (right == null && (opcode == Opcode.NOT||opcode==Opcode.RND)) || (right != null);
88 public Expr getRightExpr() {
92 public Expr getLeftExpr() {
96 public Set freeVars() {
97 Set lset=left.freeVars();
100 rset=right.freeVars();
108 public String name() {
109 if (opcode==Opcode.NOT)
110 return "!("+left.name()+")";
111 if (opcode==Opcode.NOP)
113 if (opcode==Opcode.RND)
114 return "Round("+left.name()+")";
115 String name=left.name()+opcode.toString();
121 public Opcode getOpcode() {
128 public boolean equals(Map remap, Expr e) {
129 if (e==null||!(e instanceof OpExpr))
132 if (opcode!=oe.opcode)
134 if (!left.equals(remap,oe.left))
136 if ((opcode!=Opcode.NOT)&&(opcode!=Opcode.RND)&&(opcode!=Opcode.NOP))
137 if (!right.equals(remap,oe.right))
142 public DNFRule constructDNF() {
143 if (opcode==Opcode.AND) {
144 DNFRule leftd=left.constructDNF();
145 DNFRule rightd=right.constructDNF();
146 return leftd.and(rightd);
147 } else if (opcode==Opcode.OR) {
148 DNFRule leftd=left.constructDNF();
149 DNFRule rightd=right.constructDNF();
150 return leftd.or(rightd);
151 } else if (opcode==Opcode.NOT) {
152 DNFRule leftd=left.constructDNF();
154 } else return new DNFRule(this);
157 public boolean usesDescriptor(Descriptor d) {
158 if (opcode==Opcode.GT||opcode==Opcode.GE||opcode==Opcode.LT||
159 opcode==Opcode.LE||opcode==Opcode.EQ||opcode==Opcode.NE)
160 return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
161 // return right.usesDescriptor(d);
163 return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
167 public int[] getRepairs(boolean negated) {
168 if (left instanceof RelationExpr)
169 return new int[] {AbstractRepair.MODIFYRELATION};
170 if (left instanceof SizeofExpr) {
171 boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
173 if (opcode==Opcode.EQ)
174 if (((IntegerLiteralExpr)right).getValue()==0)
175 return new int[] {AbstractRepair.REMOVEFROMRELATION};
177 return new int[] {AbstractRepair.ADDTORELATION,
178 AbstractRepair.REMOVEFROMRELATION};
179 if (((opcode==Opcode.GE)&&!negated)||
180 ((opcode==Opcode.LE)&&negated)) {
181 if (((IntegerLiteralExpr)right).getValue()==0)
184 return new int[]{AbstractRepair.ADDTORELATION}; }
186 return new int[]{AbstractRepair.REMOVEFROMRELATION};
188 if (opcode==Opcode.EQ)
189 if (((IntegerLiteralExpr)right).getValue()==0)
190 return new int[] {AbstractRepair.REMOVEFROMSET};
192 return new int[] {AbstractRepair.ADDTOSET,
193 AbstractRepair.REMOVEFROMSET};
195 if (((opcode==Opcode.GE)&&!negated)||
196 ((opcode==Opcode.LE)&&negated)) {
197 if (((IntegerLiteralExpr)right).getValue()==0)
200 return new int[] {AbstractRepair.ADDTOSET}; }
202 return new int[] {AbstractRepair.REMOVEFROMSET};
205 throw new Error("BAD");
208 public Descriptor getDescriptor() {
209 return left.getDescriptor();
212 public boolean inverted() {
213 return left.inverted();
216 public Set getInversedRelations() {
217 Set set = left.getInversedRelations();
219 set.addAll(right.getInversedRelations());
224 public Set getRequiredDescriptors() {
225 Set v = left.getRequiredDescriptors();
228 v.addAll(right.getRequiredDescriptors());
234 public void generate(CodeWriter writer, VarDescriptor dest) {
235 VarDescriptor ld = VarDescriptor.makeNew("leftop");
236 left.generate(writer, ld);
237 VarDescriptor rd = null;
240 rd = VarDescriptor.makeNew("rightop");
241 right.generate(writer, rd);
245 if (opcode == Opcode.RND) {
246 writer.outputline("int " +dest.getSafeSymbol() + " = (" +
247 ld.getSafeSymbol() + ">>3)<<3; ");
248 writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
249 } else if (opcode == Opcode.NOP) {
250 writer.outputline("int " +dest.getSafeSymbol() + " = " +
251 ld.getSafeSymbol() +"; ");
252 } else if (opcode != Opcode.NOT) { /* two operands */
254 writer.outputline("int " + dest.getSafeSymbol() + " = " +
255 ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
257 writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
261 public void prettyPrint(PrettyPrinter pp) {
263 if (opcode == Opcode.NOT) {
265 left.prettyPrint(pp);
266 } else if (opcode == Opcode.NOP) {
267 left.prettyPrint(pp);
268 } else if (opcode == Opcode.RND) {
270 left.prettyPrint(pp);
272 left.prettyPrint(pp);
273 pp.output(" " + opcode.toString() + " ");
274 assert right != null;
275 right.prettyPrint(pp);
280 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
281 TypeDescriptor lt = left.typecheck(sa);
282 TypeDescriptor rt = right == null ? null : right.typecheck(sa);
286 } else if (right != null && rt == null) {
292 // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
293 // either that or we use a isvalid clause to check for null
296 if (lt != ReservedTypeDescriptor.INT) {
297 sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
302 if (rt != ReservedTypeDescriptor.INT) {
303 sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
313 this.td = ReservedTypeDescriptor.INT;