001    /* Copyright 2000, 2001, Compaq Computer Corporation */
002    
003    package escjava.translate;
004    
005    
006    import javafe.ast.*;
007    import escjava.ast.*;
008    import escjava.ast.TagConstants;
009    import escjava.tc.Types;
010    
011    import javafe.util.Assert;
012    import javafe.util.Info;
013    import javafe.util.Location;
014    
015    
016    public abstract class Purity {
017    
018      //// The decoration for purity, plus getters and setters for it
019    
020      /** Decorates <code>VarInit</code> nodes with purity information.
021        Null means a <code>VarInit</code> is pure; non-null means it's
022        impure.  Also used by <code>Translate</code> class to decorate
023        <code>LocalVarDecl</code>s marked with "uninitialized" with the
024        declaration of the corresponding boolean that keeps track of the
025        variable's initialization state. */
026    
027      static ASTDecoration translateDecoration
028        = new ASTDecoration("translateDecoration");
029    
030      /** Return true iff <code>expr</code> or any of its subexpressions
031        mutates the heap or local variables.  Requires that
032        <code>expr</code> or an expression containing it has been
033        decorated by a call to <code>decorate</code>. */
034    
035      public static boolean impure(VarInit expr) {
036        return translateDecoration.get(expr) != null;
037      }
038    
039      /** Return true iff neither <code>expr</code> nor any of its
040        subexpressions mutate the heap or local variables.  Requires that
041        <code>expr</code> or an expression containing it has been
042        decorated by a call to <code>decorate</code>. */
043    
044      public static boolean pure(VarInit expr) {
045        return translateDecoration.get(expr) == null;
046      }
047    
048      /** Set the decoration indicating the <code>expr</code> is
049        impure. */
050    
051      private static void makeImpure(VarInit expr) {
052        translateDecoration.set(expr, translateDecoration);
053      }
054    
055    
056      //// Traversal
057    
058      /** Decorate <code>expr</code> and its subexpressions with purity
059        information. */
060    
061      public static void decorate(VarInit expr) {
062          // Info.out("Decorate "+expr);
063        int tag = expr.getTag();
064    
065        switch (tag) {
066        case TagConstants.SETCOMPEXPR:
067        case TagConstants.NEWINSTANCEEXPR:
068        case TagConstants.ASSIGN:
069        case TagConstants.ASGMUL:
070        case TagConstants.ASGADD: case TagConstants.ASGSUB:
071        case TagConstants.ASGLSHIFT: case TagConstants.ASGRSHIFT:
072        case TagConstants.ASGURSHIFT: case TagConstants.ASGBITAND:
073        case TagConstants.ASGBITOR: case TagConstants.ASGBITXOR:
074        case TagConstants.ASGDIV: case TagConstants.ASGREM:
075        case TagConstants.INC: case TagConstants.DEC:
076        case TagConstants.POSTFIXINC: case TagConstants.POSTFIXDEC:
077        case TagConstants.METHODINVOCATION:
078          for (int i = 0; i < expr.childCount(); i++) {
079            Object n = expr.childAt(i);
080            if (n instanceof VarInit)
081              decorate((VarInit)n);
082          }
083          makeImpure(expr);
084          return;
085    
086        case TagConstants.THISEXPR:
087        case TagConstants.BOOLEANLIT: 
088        case TagConstants.STRINGLIT:
089        case TagConstants.CHARLIT:
090        case TagConstants.DOUBLELIT: 
091        case TagConstants.FLOATLIT:
092        case TagConstants.INTLIT:
093        case TagConstants.LONGLIT:
094        case TagConstants.NULLLIT:
095        case TagConstants.VARIABLEACCESS:
096        case TagConstants.CLASSLITERAL:
097        case TagConstants.TYPEEXPR:  // FIXME - TYPE-EQUIV
098          return;
099    
100        case TagConstants.ARRAYINIT: 
101        case TagConstants.ARRAYREFEXPR:
102        case TagConstants.NEWARRAYEXPR:
103        case TagConstants.CONDEXPR:
104        case TagConstants.INSTANCEOFEXPR:
105        case TagConstants.CASTEXPR:
106        case TagConstants.OR: case TagConstants.AND:
107        case TagConstants.BITOR: case TagConstants.BITXOR:
108        case TagConstants.BITAND: case TagConstants.NE:
109        case TagConstants.EQ: case TagConstants.GE:
110        case TagConstants.GT: case TagConstants.LE:
111        case TagConstants.LT: case TagConstants.LSHIFT:
112        case TagConstants.RSHIFT: case TagConstants.URSHIFT:
113        case TagConstants.ADD: case TagConstants.SUB:
114        case TagConstants.STAR:
115        case TagConstants.DIV: case TagConstants.MOD:
116        case TagConstants.UNARYSUB: case TagConstants.UNARYADD:
117        case TagConstants.NOT: case TagConstants.BITNOT:
118        case TagConstants.PARENEXPR:
119        case TagConstants.FIELDACCESS:
120          {
121            boolean impure = false;
122            for (int i = 0; i < expr.childCount(); i++) {
123              Object n = expr.childAt(i);
124              if (n instanceof VarInit) {
125                VarInit child = (VarInit)n;
126                decorate(child);
127                impure = impure || impure(child);
128              }
129            }
130            if (impure) makeImpure(expr);
131            return;
132          }
133    
134        default:
135          if (expr instanceof GeneralizedQuantifiedExpr) {
136            GeneralizedQuantifiedExpr q = (GeneralizedQuantifiedExpr)expr;
137            boolean impure = false;
138            decorate(q.expr);
139            impure = impure || impure(q.expr);
140            if (q.rangeExpr != null) {
141                decorate(q.rangeExpr);
142                impure = impure || impure(q.rangeExpr);
143            }
144            if (impure) makeImpure(expr);
145            if (impure) {
146                javafe.util.ErrorSet.error(q.getStartLoc(),
147                    "A quantified expression may not contain impure expressions");
148            }
149            return;
150          } else {
151              //@ unreachable;
152              Assert.fail("Tag " + TagConstants.toString(tag) + " " +
153                        Location.toString(expr.getStartLoc()) + " " + expr);
154          }
155        }
156      }
157    }