1 24 25 package org.aspectj.compiler.base.ast; 26 27 import org.aspectj.compiler.base.JavaCompiler; 28 import org.aspectj.compiler.base.AssignmentCheckerPass; 29 import org.aspectj.compiler.base.CodeWriter; 30 import org.aspectj.compiler.base.FlowCheckerPass; 31 import org.aspectj.compiler.base.ByteCodeCleanupPass; 32 33 import org.aspectj.compiler.base.bcg.CodeBuilder; 34 import org.aspectj.compiler.base.bcg.Label; 35 36 42 public class TriTestExpr extends Expr { 43 44 public Type discoverType() { 46 Type testTy = getTest().getType(); 47 if (testTy != getTypeManager().booleanType) { 48 showError("Incompatable type for ?: Can't convert " + testTy.getString() + " to boolean"); 49 } 50 Expr trueExpr = getTrue(); 51 Expr falseExpr = getFalse(); 52 Type trueTy = trueExpr.getType(); 53 Type falseTy = falseExpr.getType(); 54 55 if (trueTy == falseTy) { 56 return trueTy; 57 } else if (trueTy.isNumeric() && falseTy.isNumeric()) { 58 if ((trueTy instanceof ShortType && falseTy instanceof ByteType) || 59 (trueTy instanceof ByteType && falseTy instanceof ShortType)) { 60 return getTypeManager().shortType; 61 } else if (trueExpr instanceof IntLiteralExpr && 62 trueTy instanceof IntType && 63 trueExpr.isAssignableTo(falseTy)) { 64 return falseTy; 65 } else if (falseExpr instanceof IntLiteralExpr && 66 falseTy instanceof IntType && 67 falseExpr.isAssignableTo(trueTy)) { 68 return trueTy; 69 } else { 70 return getTypeManager().binaryNumericPromotion(trueTy, falseTy); 71 } 72 } else if (trueTy.isReferenceType() && falseTy.isReferenceType()) { 73 if (trueTy.isAssignableFrom(falseTy)) { 74 return trueTy; 75 } else if (falseTy.isAssignableFrom(trueTy)) { 76 return falseTy; 77 } else { 78 showError("Incompatable type for ?: Can't convert between " + trueTy.getString() + " and " + falseTy.getString()); 79 return trueTy; 80 } 81 } else { 82 showError("Incompatable type for ?: Can't convert between " + trueTy.getString() + " and " + falseTy.getString()); 83 return trueTy; 84 } 85 } 86 87 public void checkSpec() { 88 if (_false instanceof AssignExpr) { 90 _false.showError("assignment expression not allowed here"); 91 } 92 } 93 94 public void preAssignmentCheck(AssignmentCheckerPass walker) { 95 getType(); 96 } 97 98 public ASTObject postAssignmentCheck(AssignmentCheckerPass walker) { 99 setType(null); 100 if ((getTrue() instanceof LiteralExpr) && 101 (getFalse() instanceof LiteralExpr)) { 102 if (getTest().isConstantTrue()) { 103 return getTrue(); 104 } else if (getTest().isConstantFalse()) { 105 return getFalse(); 106 } 107 } 108 return this; 109 } 110 111 public void unparse(CodeWriter writer) { 112 writer.write(test); 113 writer.writeOp("?"); 114 writer.write(_true); 115 writer.writeOp(":"); 116 writer.write(_false); 117 } 118 119 122 public void walkFlow(FlowCheckerPass w) { 123 w.processBoolean(getTest()); 125 FlowCheckerPass.Vars p0 = w.getVars(); 126 127 if (getType().isBoolean()) { 128 w.setVars(p0.getTrue()); 129 w.processBoolean(getTrue()); 130 FlowCheckerPass.Vars p1 = w.getVars(); 131 132 w.setVars(p0.getFalse()); 133 w.processBoolean(getFalse()); 134 FlowCheckerPass.Vars p2 = w.getVars(); 135 136 w.setVars(p1.getTrue().join(p2.getTrue()), 137 p1.getFalse().join(p2.getFalse())); 138 } else { 139 w.setVars(p0.getTrue()); 140 w.process(getTrue()); 141 FlowCheckerPass.Vars t1 = w.getVars(); 142 143 w.setVars(p0.getFalse()); 144 w.process(getFalse()); 145 FlowCheckerPass.Vars t2 = w.getVars(); 146 147 w.setVars(t1.join(t2)); 148 } 149 } 150 151 public void normalizeFlow(FlowCheckerPass w) {} 152 153 156 public ASTObject postCleanup(ByteCodeCleanupPass w) { 157 if (getTest().isConstantTrue()) { 158 return getTrue(); 159 } else if (getTest().isConstantFalse()) { 160 return getFalse(); 161 } else { 162 return this; 163 } 164 } 165 166 protected void cgValue(CodeBuilder cb) { 169 Type ty = getType(); 170 Label trueLab = cb.genLabel(); 171 Label falseLab = cb.genLabel(); 172 Label endLab = cb.genLabel(); 173 test.cgTest(cb, trueLab, falseLab); 174 cb.emitLabel(trueLab); 175 _true.cgValue(cb, ty); 176 cb.emitJump(endLab); 177 cb.emitLabel(falseLab); 178 cb.popStack(ty.getSlotCount()); 179 _false.cgValue(cb, ty); 180 cb.emitLabel(endLab); 181 } 182 protected void cgEffect(CodeBuilder cb) { 183 Label trueLab = cb.genLabel(); 184 Label falseLab = cb.genLabel(); 185 Label endLab = cb.genLabel(); 186 test.cgTest(cb, trueLab, falseLab); 187 cb.emitLabel(trueLab); 188 _true.cgEffect(cb); 189 cb.emitJump(endLab); 190 cb.emitLabel(falseLab); 191 _false.cgEffect(cb); 192 cb.emitLabel(endLab); 193 } 194 protected void cgTest(CodeBuilder cb, Label tdest, Label fdest) { 195 Label trueLab = cb.genLabel(); 196 Label falseLab = cb.genLabel(); 197 test.cgTest(cb, trueLab, falseLab); 198 cb.emitLabel(trueLab); 199 _true.cgTest(cb, tdest, fdest); 200 cb.emitLabel(falseLab); 201 _false.cgTest(cb, tdest, fdest); 202 } 203 204 protected Expr test; 206 public Expr getTest() { return test; } 207 public void setTest(Expr _test) { 208 if (_test != null) _test.setParent(this); 209 test = _test; 210 } 211 212 protected Expr _true; 213 public Expr getTrue() { return _true; } 214 public void setTrue(Expr __true) { 215 if (__true != null) __true.setParent(this); 216 _true = __true; 217 } 218 219 protected Expr _false; 220 public Expr getFalse() { return _false; } 221 public void setFalse(Expr __false) { 222 if (__false != null) __false.setParent(this); 223 _false = __false; 224 } 225 226 public TriTestExpr(SourceLocation location, Expr _test, Expr __true, Expr __false) { 227 super(location); 228 setTest(_test); 229 setTrue(__true); 230 setFalse(__false); 231 } 232 protected TriTestExpr(SourceLocation source) { 233 super(source); 234 } 235 236 public ASTObject copyWalk(CopyWalker walker) { 237 TriTestExpr ret = new TriTestExpr(getSourceLocation()); 238 ret.preCopy(walker, this); 239 if (test != null) ret.setTest( (Expr)walker.process(test) ); 240 if (_true != null) ret.setTrue( (Expr)walker.process(_true) ); 241 if (_false != null) ret.setFalse( (Expr)walker.process(_false) ); 242 return ret; 243 } 244 245 public ASTObject getChildAt(int childIndex) { 246 switch(childIndex) { 247 case 0: return test; 248 case 1: return _true; 249 case 2: return _false; 250 default: return super.getChildAt(childIndex); 251 } 252 } 253 public String getChildNameAt(int childIndex) { 254 switch(childIndex) { 255 case 0: return "test"; 256 case 1: return "true"; 257 case 2: return "false"; 258 default: return super.getChildNameAt(childIndex); 259 } 260 } 261 public void setChildAt(int childIndex, ASTObject child) { 262 switch(childIndex) { 263 case 0: setTest((Expr)child); return; 264 case 1: setTrue((Expr)child); return; 265 case 2: setFalse((Expr)child); return; 266 default: super.setChildAt(childIndex, child); return; 267 } 268 } 269 public int getChildCount() { 270 return 3; 271 } 272 273 public String getDefaultDisplayName() { 274 return "TriTestExpr()"; 275 } 276 277 } 279 | Popular Tags |