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 }