1 19 20 25 26 27 package soot.jimple.toolkits.typing.integer; 28 29 import soot.*; 30 import soot.jimple.*; 31 import soot.util.*; 32 import java.util.*; 33 import java.util.*; 34 35 36 class TypeVariable implements Comparable 37 { 38 private static final boolean DEBUG = false; 39 40 private final int id; 41 private final TypeResolver resolver; 42 43 private TypeVariable rep = this; 44 private int rank = 0; 45 46 private TypeNode approx; 47 private TypeNode inv_approx; 48 49 private TypeNode type; 50 51 private List parents = Collections.unmodifiableList(new LinkedList()); 52 private List children = Collections.unmodifiableList(new LinkedList()); 53 54 public TypeVariable(int id, TypeResolver resolver) 55 { 56 this.id = id; 57 this.resolver = resolver; 58 } 59 60 public TypeVariable(int id, TypeResolver resolver, TypeNode type) 61 { 62 this.id = id; 63 this.resolver = resolver; 64 this.type = type; 65 approx = type; 66 inv_approx = type; 67 } 68 69 public int hashCode() 70 { 71 if(rep != this) 72 { 73 return ecr().hashCode(); 74 } 75 76 return id; 77 } 78 79 public boolean equals(Object obj) 80 { 81 if(rep != this) 82 { 83 return ecr().equals(obj); 84 } 85 86 if(obj == null) 87 { 88 return false; 89 } 90 91 if(!obj.getClass().equals(getClass())) 92 { 93 return false; 94 } 95 96 TypeVariable ecr = ((TypeVariable) obj).ecr(); 97 98 if(ecr != this) 99 { 100 return false; 101 } 102 103 return true; 104 } 105 106 public int compareTo(Object o) 107 { 108 if(rep != this) 109 { 110 return ecr().compareTo(o); 111 } 112 113 return id - ((TypeVariable) o).ecr().id; 114 } 115 116 private TypeVariable ecr() 117 { 118 if(rep != this) 119 { 120 rep = rep.ecr(); 121 } 122 123 return rep; 124 } 125 126 public TypeVariable union(TypeVariable var) throws TypeException 127 { 128 if(rep != this) 129 { 130 return ecr().union(var); 131 } 132 133 TypeVariable y = var.ecr(); 134 135 if(this == y) 136 { 137 return this; 138 } 139 140 if(rank > y.rank) 141 { 142 y.rep = this; 143 144 merge(y); 145 y.clear(); 146 147 return this; 148 } 149 150 rep = y; 151 if(rank == y.rank) 152 { 153 y.rank++; 154 } 155 156 y.merge(this); 157 clear(); 158 159 return y; 160 } 161 162 private void clear() 163 { 164 inv_approx = null; 165 approx = null; 166 type = null; 167 parents = null; 168 children = null; 169 } 170 171 private void merge(TypeVariable var) throws TypeException 172 { 173 if(type == null) 175 { 176 type = var.type; 177 } 178 else if(var.type != null) 179 { 180 error("Type Error(22): Attempt to merge two types."); 181 } 182 183 { 185 Set set = new TreeSet(parents); 186 set.addAll(var.parents); 187 set.remove(this); 188 parents = Collections.unmodifiableList(new LinkedList(set)); 189 } 190 191 { 193 Set set = new TreeSet(children); 194 set.addAll(var.children); 195 set.remove(this); 196 children = Collections.unmodifiableList(new LinkedList(set)); 197 } 198 } 199 200 public int id() 201 { 202 if(rep != this) 203 { 204 return ecr().id(); 205 } 206 207 return id; 208 } 209 210 public void addParent(TypeVariable variable) 211 { 212 if(rep != this) 213 { 214 ecr().addParent(variable); 215 return; 216 } 217 218 TypeVariable var = variable.ecr(); 219 220 if(var == this) 221 { 222 return; 223 } 224 225 { 226 Set set = new TreeSet(parents); 227 set.add(var); 228 parents = Collections.unmodifiableList(new LinkedList(set)); 229 } 230 231 { 232 Set set = new TreeSet(var.children); 233 set.add(this); 234 var.children = Collections.unmodifiableList(new LinkedList(set)); 235 } 236 } 237 238 public void removeParent(TypeVariable variable) 239 { 240 if(rep != this) 241 { 242 ecr().removeParent(variable); 243 return; 244 } 245 246 TypeVariable var = variable.ecr(); 247 248 { 249 Set set = new TreeSet(parents); 250 set.remove(var); 251 parents = Collections.unmodifiableList(new LinkedList(set)); 252 } 253 254 { 255 Set set = new TreeSet(var.children); 256 set.remove(this); 257 var.children = Collections.unmodifiableList(new LinkedList(set)); 258 } 259 } 260 261 public void addChild(TypeVariable variable) 262 { 263 if(rep != this) 264 { 265 ecr().addChild(variable); 266 return; 267 } 268 269 TypeVariable var = variable.ecr(); 270 271 if(var == this) 272 { 273 return; 274 } 275 276 { 277 Set set = new TreeSet(children); 278 set.add(var); 279 children = Collections.unmodifiableList(new LinkedList(set)); 280 } 281 282 { 283 Set set = new TreeSet(var.parents); 284 set.add(this); 285 var.parents = Collections.unmodifiableList(new LinkedList(set)); 286 } 287 } 288 289 public void removeChild(TypeVariable variable) 290 { 291 if(rep != this) 292 { 293 ecr().removeChild(variable); 294 return; 295 } 296 297 TypeVariable var = variable.ecr(); 298 299 { 300 Set set = new TreeSet(children); 301 set.remove(var); 302 children = Collections.unmodifiableList(new LinkedList(set)); 303 } 304 305 { 306 Set set = new TreeSet(var.parents); 307 set.remove(this); 308 var.parents = Collections.unmodifiableList(new LinkedList(set)); 309 } 310 } 311 312 public List parents() 313 { 314 if(rep != this) 315 { 316 return ecr().parents(); 317 } 318 319 return parents; 320 } 321 322 public List children() 323 { 324 if(rep != this) 325 { 326 return ecr().children(); 327 } 328 329 return children; 330 } 331 332 public TypeNode approx() 333 { 334 if(rep != this) 335 { 336 return ecr().approx(); 337 } 338 339 return approx; 340 } 341 342 public TypeNode inv_approx() 343 { 344 if(rep != this) 345 { 346 return ecr().inv_approx(); 347 } 348 349 return inv_approx; 350 } 351 352 public TypeNode type() 353 { 354 if(rep != this) 355 { 356 return ecr().type(); 357 } 358 359 return type; 360 } 361 362 static void error(String message) throws TypeException 363 { 364 try 365 { 366 throw new TypeException(message); 367 } 368 catch(TypeException e) 369 { 370 if(DEBUG) 371 { 372 e.printStackTrace(); 373 } 374 throw e; 375 } 376 } 377 378 380 public static void computeApprox(TreeSet workList) throws TypeException 381 { 382 while(workList.size() > 0) 383 { 384 TypeVariable var = (TypeVariable) workList.first(); 385 workList.remove(var); 386 387 var.fixApprox(workList); 388 } 389 } 390 391 public static void computeInvApprox(TreeSet workList) throws TypeException 392 { 393 while(workList.size() > 0) 394 { 395 TypeVariable var = (TypeVariable) workList.first(); 396 workList.remove(var); 397 398 var.fixInvApprox(workList); 399 } 400 } 401 402 private void fixApprox(TreeSet workList) throws TypeException 403 { 404 if(rep != this) 405 { 406 ecr().fixApprox(workList); 407 return; 408 } 409 410 for(Iterator i = parents.iterator(); i.hasNext();) 411 { 412 TypeVariable parent = ((TypeVariable) i.next()).ecr(); 413 414 if(parent.approx == null) 415 { 416 parent.approx = approx; 417 workList.add(parent); 418 } 419 else 420 { 421 TypeNode type = parent.approx.lca_2(approx); 422 423 if(type != parent.approx) 424 { 425 parent.approx = type; 426 workList.add(parent); 427 } 428 } 429 } 430 431 if(type != null) 432 { 433 approx = type; 434 } 435 } 436 437 private void fixInvApprox(TreeSet workList) throws TypeException 438 { 439 if(rep != this) 440 { 441 ecr().fixInvApprox(workList); 442 return; 443 } 444 445 for(Iterator i = children.iterator(); i.hasNext();) 446 { 447 TypeVariable child = ((TypeVariable) i.next()).ecr(); 448 449 if(child.inv_approx == null) 450 { 451 child.inv_approx = inv_approx; 452 workList.add(child); 453 } 454 else 455 { 456 TypeNode type = child.inv_approx.gcd_2(inv_approx); 457 458 if(type != child.inv_approx) 459 { 460 child.inv_approx = type; 461 workList.add(child); 462 } 463 } 464 } 465 466 if(type != null) 467 { 468 inv_approx = type; 469 } 470 } 471 472 public String toString() 473 { 474 if(rep != this) 475 { 476 return ecr().toString(); 477 } 478 479 StringBuffer s = new StringBuffer (); 480 s.append(",[parents:"); 481 482 { 483 boolean comma = false; 484 485 for(Iterator i = parents.iterator(); i.hasNext(); ) 486 { 487 if(comma) 488 { 489 s.append(","); 490 } 491 else 492 { 493 comma = true; 494 } 495 s.append(((TypeVariable) i.next()).id()); 496 } 497 } 498 499 s.append("],[children:"); 500 501 { 502 boolean comma = false; 503 504 for(Iterator i = children.iterator(); i.hasNext(); ) 505 { 506 if(comma) 507 { 508 s.append(","); 509 } 510 else 511 { 512 comma = true; 513 } 514 s.append(((TypeVariable) i.next()).id()); 515 } 516 } 517 518 s.append("]"); 519 return "[id:" + id + ((type != null) ? (",type:" + type) : "") + ",approx:" + approx + ",inv_approx:" + inv_approx + s + "]"; 520 } 521 522 public void fixParents() 523 { 524 if(rep != this) 525 { 526 ecr().fixParents(); 527 return; 528 } 529 530 { 531 Set set = new TreeSet(parents); 532 parents = Collections.unmodifiableList(new LinkedList(set)); 533 } 534 } 535 536 public void fixChildren() 537 { 538 if(rep != this) 539 { 540 ecr().fixChildren(); 541 return; 542 } 543 544 { 545 Set set = new TreeSet(children); 546 children = Collections.unmodifiableList(new LinkedList(set)); 547 } 548 } 549 550 } 551 | Popular Tags |