KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > nativequery > analysis > BloatExprBuilderVisitor


1 /* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com
2
3 This file is part of the db4o open source object database.
4
5 db4o is free software; you can redistribute it and/or modify it under
6 the terms of version 2 of the GNU General Public License as published
7 by the Free Software Foundation and as clarified by db4objects' GPL
8 interpretation policy, available at
9 http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
10 Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
11 Suite 350, San Mateo, CA 94403, USA.
12
13 db4o is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

21 package com.db4o.nativequery.analysis;
22
23 import java.util.*;
24
25 import EDU.purdue.cs.bloat.cfg.*;
26 import EDU.purdue.cs.bloat.editor.*;
27 import EDU.purdue.cs.bloat.tree.*;
28
29 import com.db4o.nativequery.*;
30 import com.db4o.nativequery.bloat.*;
31 import com.db4o.nativequery.expr.*;
32 import com.db4o.nativequery.expr.build.*;
33 import com.db4o.nativequery.expr.cmp.*;
34 import com.db4o.nativequery.expr.cmp.field.*;
35
36 public class BloatExprBuilderVisitor extends TreeVisitor {
37
38     // TODO discuss: drop or make configurable
39
private final static int MAX_DEPTH = 10;
40
41     private final static String JavaDoc[] PRIMITIVE_WRAPPER_NAMES = {
42             Boolean JavaDoc.class.getName(), Byte JavaDoc.class.getName(),
43             Short JavaDoc.class.getName(), Character JavaDoc.class.getName(),
44             Integer JavaDoc.class.getName(), Long JavaDoc.class.getName(),
45             Double JavaDoc.class.getName(), Float JavaDoc.class.getName(),
46             String JavaDoc.class.getName(), };
47
48     static {
49         Arrays.sort(PRIMITIVE_WRAPPER_NAMES);
50     }
51
52     private final static ExpressionBuilder BUILDER = new ExpressionBuilder();
53
54     private final static Map BUILDERS = new HashMap();
55
56     private final static Map OP_SYMMETRY = new HashMap();
57
58     private static class ComparisonBuilder {
59         private ComparisonOperator op;
60
61         public ComparisonBuilder(ComparisonOperator op) {
62             this.op = op;
63         }
64
65         public Expression buildComparison(FieldValue fieldValue,
66                 ComparisonOperand valueExpr) {
67             return new ComparisonExpression(fieldValue, valueExpr, op);
68         }
69     }
70
71     private static class NegateComparisonBuilder extends ComparisonBuilder {
72         public NegateComparisonBuilder(ComparisonOperator op) {
73             super(op);
74         }
75
76         public Expression buildComparison(FieldValue fieldValue,
77                 ComparisonOperand valueExpr) {
78             return BUILDER.not(super.buildComparison(fieldValue, valueExpr));
79         }
80     }
81
82     static {
83         BUILDERS.put(new Integer JavaDoc(IfStmt.EQ), new ComparisonBuilder(
84                 ComparisonOperator.EQUALS));
85         BUILDERS.put(new Integer JavaDoc(IfStmt.NE), new NegateComparisonBuilder(
86                 ComparisonOperator.EQUALS));
87         BUILDERS.put(new Integer JavaDoc(IfStmt.LT), new ComparisonBuilder(
88                 ComparisonOperator.SMALLER));
89         BUILDERS.put(new Integer JavaDoc(IfStmt.GT), new ComparisonBuilder(
90                 ComparisonOperator.GREATER));
91         BUILDERS.put(new Integer JavaDoc(IfStmt.LE), new NegateComparisonBuilder(
92                 ComparisonOperator.GREATER));
93         BUILDERS.put(new Integer JavaDoc(IfStmt.GE), new NegateComparisonBuilder(
94                 ComparisonOperator.SMALLER));
95
96         OP_SYMMETRY.put(new Integer JavaDoc(IfStmt.EQ), new Integer JavaDoc(IfStmt.EQ));
97         OP_SYMMETRY.put(new Integer JavaDoc(IfStmt.NE), new Integer JavaDoc(IfStmt.NE));
98         OP_SYMMETRY.put(new Integer JavaDoc(IfStmt.LT), new Integer JavaDoc(IfStmt.GT));
99         OP_SYMMETRY.put(new Integer JavaDoc(IfStmt.GT), new Integer JavaDoc(IfStmt.LT));
100         OP_SYMMETRY.put(new Integer JavaDoc(IfStmt.LE), new Integer JavaDoc(IfStmt.GE));
101         OP_SYMMETRY.put(new Integer JavaDoc(IfStmt.GE), new Integer JavaDoc(IfStmt.LE));
102     }
103
104     private Expression expr;
105
106     private Object JavaDoc retval;
107
108     private Map seenBlocks = new HashMap();
109
110     private BloatUtil bloatUtil;
111
112     private LinkedList methodStack = new LinkedList();
113
114     private LinkedList localStack = new LinkedList();
115
116     private int retCount = 0;
117
118     private int blockCount = 0;
119
120     public BloatExprBuilderVisitor(BloatUtil bloatUtil) {
121         this.bloatUtil = bloatUtil;
122         localStack.addLast(new ComparisonOperand[] {
123                 PredicateFieldRoot.INSTANCE, CandidateFieldRoot.INSTANCE });
124     }
125
126     private Object JavaDoc purgeReturnValue() {
127         Object JavaDoc expr = this.retval;
128         retval(null);
129         return expr;
130     }
131
132     private void expression(Expression expr) {
133         retval(expr);
134         this.expr = expr;
135     }
136
137     private void retval(Object JavaDoc expr) {
138         this.retval = expr;
139     }
140
141     private ComparisonBuilder builder(int op) {
142         return (ComparisonBuilder) BUILDERS.get(new Integer JavaDoc(op));
143     }
144
145     public Expression expression() {
146         if (expr == null && isSingleReturn() && retval instanceof ConstValue) {
147             expression(asExpression(retval));
148         }
149         return (checkComparisons(expr) ? expr : null);
150     }
151
152     private boolean isSingleReturn() {
153         return retCount == 1 && blockCount == 4; // one plus source,init,sink
154
}
155
156     private boolean checkComparisons(Expression expr) {
157         if (expr == null) {
158             return true;
159         }
160         final boolean[] result = { true };
161         ExpressionVisitor visitor = new TraversingExpressionVisitor() {
162             public void visit(ComparisonExpression expression) {
163                 if (expression.left().root() != CandidateFieldRoot.INSTANCE) {
164                     result[0] = false;
165                 }
166             }
167         };
168         expr.accept(visitor);
169         return result[0];
170     }
171
172     public void visitIfZeroStmt(IfZeroStmt stmt) {
173         stmt.expr().visit(this);
174         Object JavaDoc retval = purgeReturnValue();
175         boolean cmpNull = false;
176         if (retval instanceof FieldValue) {
177             // TODO: merge boolean and number primitive handling
178
Expression forced = identityOrBoolComparisonOrNull(retval);
179             if (forced != null) {
180                 retval = forced;
181             } else {
182                 FieldValue fieldVal = (FieldValue) retval;
183                 String JavaDoc fieldType = (String JavaDoc)fieldVal.tag();
184                 Object JavaDoc constVal=null;
185                 if(fieldType.length()==1) {
186                     constVal=new Integer JavaDoc(0);
187                 }
188                 retval = new ComparisonExpression(fieldVal,
189                         new ConstValue(constVal), ComparisonOperator.EQUALS);
190                 cmpNull = true;
191             }
192         }
193         if (retval instanceof Expression) {
194             Expression expr = (Expression) retval;
195             if (stmt.comparison() == IfStmt.EQ && !cmpNull
196                     || stmt.comparison() == IfStmt.NE && cmpNull) {
197                 expr = BUILDER.not(expr);
198             }
199             expression(buildComparison(stmt, expr));
200             return;
201         }
202         if (!(retval instanceof ThreeWayComparison)) {
203             expression(null);
204             return;
205         }
206         ThreeWayComparison cmp = (ThreeWayComparison) retval;
207         Expression expr = null;
208         int comparison = stmt.comparison();
209         if (cmp.swapped()) {
210             comparison = ((Integer JavaDoc) OP_SYMMETRY.get(new Integer JavaDoc(comparison)))
211                     .intValue();
212         }
213         switch (comparison) {
214         case IfStmt.EQ:
215             expr = new ComparisonExpression(cmp.left(), cmp.right(),
216                     ComparisonOperator.EQUALS);
217             break;
218         case IfStmt.NE:
219             expr = BUILDER.not(new ComparisonExpression(cmp.left(),
220                     cmp.right(), ComparisonOperator.EQUALS));
221             break;
222         case IfStmt.LT:
223             expr = new ComparisonExpression(cmp.left(), cmp.right(),
224                     ComparisonOperator.SMALLER);
225             break;
226         case IfStmt.GT:
227             expr = new ComparisonExpression(cmp.left(), cmp.right(),
228                     ComparisonOperator.GREATER);
229             break;
230         case IfStmt.LE:
231             expr = BUILDER.not(new ComparisonExpression(cmp.left(),
232                     cmp.right(), ComparisonOperator.GREATER));
233             break;
234         case IfStmt.GE:
235             expr = BUILDER.not(new ComparisonExpression(cmp.left(),
236                     cmp.right(), ComparisonOperator.SMALLER));
237             break;
238         default:
239             break;
240         }
241         expression(buildComparison(stmt, expr));
242     }
243
244     public void visitIfCmpStmt(IfCmpStmt stmt) {
245         stmt.left().visit(this);
246         Object JavaDoc left = purgeReturnValue();
247         stmt.right().visit(this);
248         Object JavaDoc right = purgeReturnValue();
249         int op = stmt.comparison();
250         if ((left instanceof ComparisonOperand)
251                 && (right instanceof FieldValue)) {
252             FieldValue rightField = (FieldValue) right;
253             if (rightField.root() == CandidateFieldRoot.INSTANCE) {
254                 Object JavaDoc swap = left;
255                 left = right;
256                 right = swap;
257                 op = ((Integer JavaDoc) OP_SYMMETRY.get(new Integer JavaDoc(op))).intValue();
258             }
259         }
260         if (!(left instanceof FieldValue)
261                 || !(right instanceof ComparisonOperand)) {
262             expression(null);
263             return;
264         }
265         FieldValue fieldExpr = (FieldValue) left;
266         ComparisonOperand valueExpr = (ComparisonOperand) right;
267
268         Expression cmp = buildComparison(stmt, builder(op).buildComparison(
269                 fieldExpr, valueExpr));
270         expression(cmp);
271     }
272
273     public void visitExprStmt(ExprStmt stmt) {
274         super.visitExprStmt(stmt);
275     }
276
277     private boolean isPrimitiveWrapper(Type type) {
278         String JavaDoc typeName=bloatUtil.normalizedClassName(type);
279         for (int idx = 0; idx < PRIMITIVE_WRAPPER_NAMES.length; idx++) {
280             if(typeName.equals(PRIMITIVE_WRAPPER_NAMES[idx])) {
281                 return true;
282             }
283         }
284         return false;
285     }
286     
287     public void visitCallExpr(CallExpr expr) {
288         boolean isStatic = (expr instanceof CallStaticExpr);
289         if (!isStatic && expr.method().name().equals("<init>")) {
290             retval(null);
291             return;
292         }
293         if (!isStatic && expr.method().name().equals("equals")) {
294             CallMethodExpr call = (CallMethodExpr) expr;
295             if (isPrimitive(call.receiver().type())) {
296                 processEqualsCall(call, ComparisonOperator.EQUALS);
297             }
298             return;
299         }
300         if(expr.method().declaringClass().equals(Type.STRING)) {
301             if(applyStringHandling(expr)) {
302                 return;
303             }
304         }
305         ComparisonOperandAnchor rcvRetval = null;
306         if (!isStatic) {
307             ((CallMethodExpr) expr).receiver().visit(this);
308             rcvRetval = (ComparisonOperandAnchor) purgeReturnValue();
309         }
310         if(isPrimitiveWrapper(expr.method().declaringClass())) {
311             if(applyPrimitiveWrapperHandling(expr,rcvRetval)) {
312                 return;
313             }
314         }
315         MemberRef methodRef = expr.method();
316         if (methodStack.contains(methodRef) || methodStack.size() > MAX_DEPTH) {
317             return;
318         }
319         methodStack.addLast(methodRef);
320         boolean addedLocals=false;
321         try {
322             List params = new ArrayList(expr.params().length + 1);
323             params.add(rcvRetval);
324             for (int idx = 0; idx < expr.params().length; idx++) {
325                 expr.params()[idx].visit(this);
326                 ComparisonOperand curparam = (ComparisonOperand) purgeReturnValue();
327                 if ((curparam instanceof ComparisonOperandAnchor)
328                         && (((ComparisonOperandAnchor) curparam).root() == CandidateFieldRoot.INSTANCE)) {
329                     retval(null);
330                     return;
331                 }
332                 params.add(curparam);
333             }
334             addedLocals=true;
335             localStack.addLast(params.toArray(new ComparisonOperand[params
336                     .size()]));
337
338             if (rcvRetval == null
339                     || rcvRetval.root() != CandidateFieldRoot.INSTANCE) {
340                 if (rcvRetval == null) {
341                     rcvRetval = new StaticFieldRoot(bloatUtil.normalizedClassName(expr
342                             .method().declaringClass()));
343                 }
344                 params.remove(0);
345                 Type[] paramTypes = expr.method().nameAndType().type()
346                         .paramTypes();
347                 Class JavaDoc[] javaParamTypes = new Class JavaDoc[paramTypes.length];
348                 for (int paramIdx = 0; paramIdx < paramTypes.length; paramIdx++) {
349                     String JavaDoc className = bloatUtil.normalizedClassName(paramTypes[paramIdx]);
350                     javaParamTypes[paramIdx] = (PRIMITIVE_CLASSES
351                             .containsKey(className) ? (Class JavaDoc) PRIMITIVE_CLASSES
352                             .get(className) : Class.forName(className));
353                 }
354                 retval(new MethodCallValue(rcvRetval, expr.method().name(),
355                         javaParamTypes, (ComparisonOperand[]) params
356                                 .toArray(new ComparisonOperand[params.size()])));
357                 return;
358             }
359
360             FlowGraph flowGraph = bloatUtil.flowGraph(methodRef
361                     .declaringClass().className(), methodRef.name());
362             if (flowGraph == null) {
363                 return;
364             }
365             if (NQDebug.LOG) {
366                 System.out
367                         .println("METHOD:" + flowGraph.method().nameAndType());
368                 flowGraph.visit(new PrintVisitor());
369             }
370             flowGraph.visit(this);
371             Object JavaDoc methodRetval = purgeReturnValue();
372             retval(methodRetval);
373         } catch (ClassNotFoundException JavaDoc e) {
374             e.printStackTrace();
375         } finally {
376             if(addedLocals) {
377                 localStack.removeLast();
378             }
379             Object JavaDoc last = methodStack.removeLast();
380             if (!last.equals(methodRef)) {
381                 throw new RuntimeException JavaDoc("method stack inconsistent: push="
382                         + methodRef + " , pop=" + last);
383             }
384         }
385     }
386
387     private boolean applyPrimitiveWrapperHandling(CallExpr expr,ComparisonOperandAnchor rcvRetval) {
388         String JavaDoc methodName = expr.method().name();
389         if(methodName.endsWith("Value")) {
390             return handlePrimitiveWrapperValueCall(rcvRetval);
391         }
392         if(methodName.equals("compareTo")) {
393             return handlePrimitiveWrapperCompareToCall(expr, rcvRetval);
394         }
395         return false;
396     }
397
398     private boolean handlePrimitiveWrapperCompareToCall(CallExpr expr, ComparisonOperandAnchor rcvRetval) {
399         ComparisonOperand left=rcvRetval;
400         expr.params()[0].visit(this);
401         ComparisonOperand right=(ComparisonOperand) purgeReturnValue();
402         retval(new ThreeWayComparison((FieldValue)left,right,false));
403         return true;
404     }
405
406     private boolean handlePrimitiveWrapperValueCall(ComparisonOperandAnchor rcvRetval) {
407         retval(rcvRetval);
408         if(rcvRetval instanceof FieldValue) {
409             FieldValue fieldval=(FieldValue)rcvRetval;
410             if(isBooleanField(fieldval)) {
411                 retval(new ComparisonExpression(fieldval,new ConstValue(Boolean.TRUE),ComparisonOperator.EQUALS));
412             }
413             if(fieldval.root().equals(CandidateFieldRoot.INSTANCE)) {
414                 return true;
415             }
416         }
417         return false;
418     }
419
420     private boolean applyStringHandling(CallExpr expr) {
421         if (expr.method().name().equals("contains")) {
422             processEqualsCall((CallMethodExpr) expr,
423                     ComparisonOperator.CONTAINS);
424             return true;
425         }
426         if (expr.method().name().equals("startsWith")) {
427             processEqualsCall((CallMethodExpr) expr,
428                     ComparisonOperator.STARTSWITH);
429             return true;
430         }
431         if (expr.method().name().equals("endsWith")) {
432             processEqualsCall((CallMethodExpr) expr,
433                     ComparisonOperator.ENDSWITH);
434             return true;
435         }
436         return false;
437     }
438
439     private final static Map PRIMITIVE_CLASSES;
440
441     static {
442         PRIMITIVE_CLASSES = new HashMap();
443         PRIMITIVE_CLASSES.put("Z", Boolean.TYPE);
444         PRIMITIVE_CLASSES.put("B", Byte.TYPE);
445         PRIMITIVE_CLASSES.put("S", Short.TYPE);
446         PRIMITIVE_CLASSES.put("C", Character.TYPE);
447         PRIMITIVE_CLASSES.put("I", Integer.TYPE);
448         PRIMITIVE_CLASSES.put("J", Long.TYPE);
449         PRIMITIVE_CLASSES.put("F", Float.TYPE);
450         PRIMITIVE_CLASSES.put("D", Double.TYPE);
451     }
452
453     private boolean isPrimitive(Type type) {
454         return Arrays.binarySearch(PRIMITIVE_WRAPPER_NAMES,
455                 bloatUtil.normalizedClassName(type)) >= 0;
456     }
457
458     private void processEqualsCall(CallMethodExpr expr, ComparisonOperator op) {
459         Expr left = expr.receiver();
460         Expr right = expr.params()[0];
461         if (!isComparableExprOperand(left) || !isComparableExprOperand(right)) {
462             throw new EarlyExitException();
463         }
464         left.visit(this);
465         Object JavaDoc leftObj = purgeReturnValue();
466         if (!(leftObj instanceof ComparisonOperand)) {
467             expression(null);
468             return;
469         }
470         ComparisonOperand leftOp = (ComparisonOperand) leftObj;
471         right.visit(this);
472         ComparisonOperand rightOp = (ComparisonOperand) purgeReturnValue();
473         if (op.isSymmetric() && isCandidateFieldValue(rightOp)
474                 && !isCandidateFieldValue(leftOp)) {
475             ComparisonOperand swap = leftOp;
476             leftOp = rightOp;
477             rightOp = swap;
478         }
479         if (!isCandidateFieldValue(leftOp) || rightOp == null) {
480             throw new EarlyExitException();
481         }
482         expression(new ComparisonExpression((FieldValue) leftOp, rightOp, op));
483     }
484
485     private boolean isCandidateFieldValue(ComparisonOperand op) {
486         return ((op instanceof FieldValue) && ((FieldValue) op).root() == CandidateFieldRoot.INSTANCE);
487     }
488
489     private boolean isComparableExprOperand(Expr expr) {
490         return (expr instanceof FieldExpr) || (expr instanceof StaticFieldExpr)
491                 || (expr instanceof CallMethodExpr)
492                 || (expr instanceof CallStaticExpr)
493                 || (expr instanceof ConstantExpr)
494                 || (expr instanceof LocalExpr);
495     }
496
497     public void visitFieldExpr(FieldExpr expr) {
498         expr.object().visit(this);
499         Object JavaDoc fieldObj = purgeReturnValue();
500         String JavaDoc fieldName = expr.field().name();
501         if (fieldObj instanceof ComparisonOperandAnchor) {
502             retval(new FieldValue((ComparisonOperandAnchor) fieldObj,
503                     fieldName, bloatUtil.normalizedClassName(expr.field().type())));
504         }
505     }
506
507     public void visitStaticFieldExpr(StaticFieldExpr expr) {
508         MemberRef field = expr.field();
509         retval(new FieldValue(new StaticFieldRoot(bloatUtil.normalizedClassName(field
510                 .declaringClass())), field.name(), bloatUtil.normalizedClassName(field
511                 .type())));
512     }
513
514     public void visitConstantExpr(ConstantExpr expr) {
515         super.visitConstantExpr(expr);
516         retval(new ConstValue(expr.value()));
517     }
518
519     public void visitLocalExpr(LocalExpr expr) {
520         super.visitLocalExpr(expr);
521         ComparisonOperand[] locals = (ComparisonOperand[]) localStack.getLast();
522         if (expr.index() >= locals.length) {
523             retval(null);
524             return;
525         }
526         retval(locals[expr.index()]);
527     }
528
529     public void visitBlock(Block block) {
530         if (!seenBlocks.containsKey(block)) {
531             super.visitBlock(block);
532             seenBlocks.put(block, retval);
533             blockCount++;
534         } else {
535             retval(seenBlocks.get(block));
536         }
537     }
538
539     public void visitFlowGraph(FlowGraph graph) {
540         try {
541             super.visitFlowGraph(graph);
542             if (expr == null) {
543                 Expression forced = identityOrBoolComparisonOrNull(retval);
544                 if (forced != null) {
545                     expression(forced);
546                 }
547             }
548         } catch (EarlyExitException exc) {
549             expr=null;
550         }
551     }
552
553     private Expression identityOrBoolComparisonOrNull(Object JavaDoc val) {
554         if (val instanceof Expression) {
555             return (Expression) val;
556         }
557         if (!(val instanceof FieldValue)) {
558             return null;
559         }
560         FieldValue fieldVal = (FieldValue) val;
561         if (fieldVal.root() != CandidateFieldRoot.INSTANCE) {
562             return null;
563         }
564         String JavaDoc fieldType = ((String JavaDoc) fieldVal.tag());
565         if (fieldType.length() != 1) {
566             return null;
567         }
568         Object JavaDoc constVal = null;
569         switch (fieldType.charAt(0)) {
570             case 'Z':
571                 constVal = Boolean.TRUE;
572                 break;
573 // case 'I':
574
// constVal = new Integer(0);
575
// break;
576
default:
577                 return null;
578         }
579         return new ComparisonExpression(fieldVal, new ConstValue(constVal),
580                 ComparisonOperator.EQUALS);
581     }
582
583     private boolean isBooleanField(FieldValue fieldVal) {
584         return isFieldType(fieldVal, "Z")||isFieldType(fieldVal, Boolean JavaDoc.class.getName());
585     }
586
587     private boolean isIntField(FieldValue fieldVal) {
588         return isFieldType(fieldVal, "I");
589     }
590
591     private boolean isFieldType(FieldValue fieldVal, String JavaDoc expType) {
592         return expType.equals(fieldVal.tag());
593     }
594
595     public void visitArithExpr(ArithExpr expr) {
596         expr.left().visit(this);
597         Object JavaDoc leftObj = purgeReturnValue();
598         if (!(leftObj instanceof ComparisonOperand)) {
599             return;
600         }
601         ComparisonOperand left = (ComparisonOperand) leftObj;
602         expr.right().visit(this);
603         Object JavaDoc rightObj = purgeReturnValue();
604         if (!(rightObj instanceof ComparisonOperand)) {
605             return;
606         }
607         ComparisonOperand right = (ComparisonOperand) rightObj;
608         boolean swapped = false;
609         if (right instanceof FieldValue) {
610             FieldValue rightField = (FieldValue) right;
611             if (rightField.root() == CandidateFieldRoot.INSTANCE) {
612                 ComparisonOperand swap = left;
613                 left = right;
614                 right = swap;
615                 swapped = true;
616             }
617         }
618         switch (expr.operation()) {
619         case ArithExpr.ADD:
620         case ArithExpr.SUB:
621         case ArithExpr.MUL:
622         case ArithExpr.DIV:
623             retval(new ArithmeticExpression(left, right,
624                     arithmeticOperator(expr.operation())));
625             break;
626         case ArithExpr.CMP:
627         case ArithExpr.CMPG:
628         case ArithExpr.CMPL:
629             if (left instanceof FieldValue) {
630                 retval(new ThreeWayComparison((FieldValue) left, right, swapped));
631             }
632             break;
633         case ArithExpr.XOR:
634             if (left instanceof FieldValue) {
635                 retval(BUILDER.not(new ComparisonExpression((FieldValue) left,
636                         right, ComparisonOperator.EQUALS)));
637             }
638             break;
639         default:
640             break;
641         }
642     }
643
644     public void visitArrayRefExpr(ArrayRefExpr expr) {
645         expr.array().visit(this);
646         ComparisonOperandAnchor arrayOp = (ComparisonOperandAnchor) purgeReturnValue();
647         expr.index().visit(this);
648         ComparisonOperand idxOp = (ComparisonOperand) purgeReturnValue();
649         if (arrayOp == null || idxOp == null
650                 || arrayOp.root() == CandidateFieldRoot.INSTANCE) {
651             retval(null);
652             return;
653         }
654         retval(new ArrayAccessValue(arrayOp, idxOp));
655     }
656
657     public void visitReturnExprStmt(ReturnExprStmt stat) {
658         stat.expr().visit(this);
659         retCount++;
660     }
661
662     private ArithmeticOperator arithmeticOperator(int bloatOp) {
663         switch (bloatOp) {
664         case ArithExpr.ADD:
665             return ArithmeticOperator.ADD;
666         case ArithExpr.SUB:
667             return ArithmeticOperator.SUBTRACT;
668         case ArithExpr.MUL:
669             return ArithmeticOperator.MULTIPLY;
670         case ArithExpr.DIV:
671             return ArithmeticOperator.DIVIDE;
672         default:
673             return null;
674         }
675     }
676
677     private Expression buildComparison(IfStmt stmt, Expression cmp) {
678         stmt.trueTarget().visit(this);
679         Object JavaDoc trueVal = purgeReturnValue();
680         stmt.falseTarget().visit(this);
681         Object JavaDoc falseVal = purgeReturnValue();
682         Expression trueExpr = asExpression(trueVal);
683         Expression falseExpr = asExpression(falseVal);
684         if (trueExpr == null || falseExpr == null) {
685             return null;
686         }
687         return BUILDER.ifThenElse(cmp, trueExpr, falseExpr);
688     }
689
690     private Expression asExpression(Object JavaDoc obj) {
691         if (obj instanceof Expression) {
692             return (Expression) obj;
693         }
694         if (obj instanceof ConstValue) {
695             Object JavaDoc val = ((ConstValue) obj).value();
696             return asExpression(val);
697         }
698         if (obj instanceof Boolean JavaDoc) {
699             return BoolConstExpression.expr(((Boolean JavaDoc) obj).booleanValue());
700         }
701         if (obj instanceof Integer JavaDoc) {
702             int exprval = ((Integer JavaDoc) obj).intValue();
703             if (exprval == 0 || exprval == 1) {
704                 return BoolConstExpression.expr(exprval == 1);
705             }
706         }
707         return null;
708     }
709     
710     private static class EarlyExitException extends RuntimeException JavaDoc {
711     }
712 }
713
Popular Tags