1 package polyglot.ext.jl.ast; 2 3 import polyglot.ast.*; 4 import polyglot.types.*; 5 import polyglot.visit.*; 6 import polyglot.util.*; 7 import java.util.*; 8 9 12 public abstract class Assign_c extends Expr_c implements Assign 13 { 14 protected Expr left; 15 protected Operator op; 16 protected Expr right; 17 18 public Assign_c(Position pos, Expr left, Operator op, Expr right) { 19 super(pos); 20 this.left = left; 21 this.op = op; 22 this.right = right; 23 } 24 25 26 public Precedence precedence() { 27 return Precedence.ASSIGN; 28 } 29 30 31 public Expr left() { 32 return this.left; 33 } 34 35 36 public Assign left(Expr left) { 37 Assign_c n = (Assign_c) copy(); 38 n.left = left; 39 return n; 40 } 41 42 43 public Operator operator() { 44 return this.op; 45 } 46 47 48 public Assign operator(Operator op) { 49 Assign_c n = (Assign_c) copy(); 50 n.op = op; 51 return n; 52 } 53 54 55 public Expr right() { 56 return this.right; 57 } 58 59 60 public Assign right(Expr right) { 61 Assign_c n = (Assign_c) copy(); 62 n.right = right; 63 return n; 64 } 65 66 67 protected Assign_c reconstruct(Expr left, Expr right) { 68 if (left != this.left || right != this.right) { 69 Assign_c n = (Assign_c) copy(); 70 n.left = left; 71 n.right = right; 72 return n; 73 } 74 75 return this; 76 } 77 78 79 public Node visitChildren(NodeVisitor v) { 80 Expr left = (Expr) visitChild(this.left, v); 81 Expr right = (Expr) visitChild(this.right, v); 82 return reconstruct(left, right); 83 } 84 85 86 87 public Node typeCheck(TypeChecker tc) throws SemanticException { 88 Type t = left.type(); 89 Type s = right.type(); 90 91 TypeSystem ts = tc.typeSystem(); 92 93 if (! (left instanceof Variable)) { 94 throw new SemanticException("Target of assignment must be a variable.", 95 position()); 96 } 97 98 if (op == ASSIGN) { 99 if (! ts.isImplicitCastValid(s, t) && 100 ! ts.equals(s, t) && 101 ! ts.numericConversionValid(t, right.constantValue())) { 102 103 throw new SemanticException("Cannot assign " + s + " to " + t + ".", 104 position()); 105 } 106 107 return type(t); 108 } 109 110 if (op == ADD_ASSIGN) { 111 if (ts.equals(t, ts.String()) && ts.canCoerceToString(s, tc.context())) { 113 return type(ts.String()); 114 } 115 116 if (t.isNumeric() && s.isNumeric()) { 117 return type(ts.promote(t, s)); 118 } 119 120 throw new SemanticException("The " + op + " operator must have " 121 + "numeric or String operands.", 122 position()); 123 } 124 125 if (op == SUB_ASSIGN || op == MUL_ASSIGN || 126 op == DIV_ASSIGN || op == MOD_ASSIGN) { 127 if (t.isNumeric() && s.isNumeric()) { 128 return type(ts.promote(t, s)); 129 } 130 131 throw new SemanticException("The " + op + " operator must have " 132 + "numeric operands.", 133 position()); 134 } 135 136 if (op == BIT_AND_ASSIGN || op == BIT_OR_ASSIGN || op == BIT_XOR_ASSIGN) { 137 if (t.isBoolean() && s.isBoolean()) { 138 return type(ts.Boolean()); 139 } 140 141 if (ts.isImplicitCastValid(t, ts.Long()) && 142 ts.isImplicitCastValid(s, ts.Long())) { 143 return type(ts.promote(t, s)); 144 } 145 146 throw new SemanticException("The " + op + " operator must have " 147 + "integral or boolean operands.", 148 position()); 149 } 150 151 if (op == SHL_ASSIGN || op == SHR_ASSIGN || op == USHR_ASSIGN) { 152 if (ts.isImplicitCastValid(t, ts.Long()) && 153 ts.isImplicitCastValid(s, ts.Long())) { 154 return type(ts.promote(t)); 156 } 157 158 throw new SemanticException("The " + op + " operator must have " 159 + "integral operands.", 160 position()); 161 } 162 163 throw new InternalCompilerError("Unrecognized assignment operator " + 164 op + "."); 165 } 166 167 public Type childExpectedType(Expr child, AscriptionVisitor av) { 168 if (child == right) { 169 TypeSystem ts = av.typeSystem(); 170 171 if (ts.numericConversionValid(left.type(), child.constantValue())) { 174 return child.type(); 175 } 176 else { 177 return left.type(); 178 } 179 } 180 181 return child.type(); 182 } 183 184 185 public boolean throwsArithmeticException() { 186 return op == DIV_ASSIGN || op == MOD_ASSIGN; 190 } 191 192 public String toString() { 193 return left + " " + op + " " + right; 194 } 195 196 197 public void prettyPrint(CodeWriter w, PrettyPrinter tr) { 198 printSubExpr(left, true, w, tr); 199 w.write(" "); 200 w.write(op.toString()); 201 w.allowBreak(2, " "); 202 printSubExpr(right, false, w, tr); 203 } 204 205 206 public void dump(CodeWriter w) { 207 super.dump(w); 208 w.allowBreak(4, " "); 209 w.begin(0); 210 w.write("(operator " + op + ")"); 211 w.end(); 212 } 213 214 abstract public Term entry(); 215 216 public List acceptCFG(CFGBuilder v, List succs) { 217 if (operator() == ASSIGN) { 218 acceptCFGAssign(v); 219 } 220 else { 221 acceptCFGOpAssign(v); 222 } 223 return succs; 224 } 225 226 229 protected abstract void acceptCFGAssign(CFGBuilder v); 230 231 234 protected abstract void acceptCFGOpAssign(CFGBuilder v); 235 236 public List throwTypes(TypeSystem ts) { 237 List l = new LinkedList(); 238 239 if (throwsArithmeticException()) { 240 l.add(ts.ArithmeticException()); 241 } 242 243 return l; 244 } 245 } 246 | Popular Tags |