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 }