    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    }