1 37 39 package com.google.gwt.dev.js.rhino; 40 41 47 48 public class Node implements Cloneable { 49 50 private static class NumberNode extends Node { 51 52 NumberNode(double number) { 53 super(TokenStream.NUMBER); 54 this.number = number; 55 } 56 57 public double getDouble() { 58 return this.number; 59 } 60 61 public boolean equals(Object o) { 62 return o instanceof NumberNode 63 && getDouble() == ((NumberNode) o).getDouble(); 64 } 65 66 private double number; 67 } 68 69 private static class StringNode extends Node { 70 71 StringNode(int type, String str) { 72 super(type); 73 if (null == str) { 74 throw new IllegalArgumentException ("StringNode: str is null"); 75 } 76 this.str = str; 77 } 78 79 82 public String getString() { 83 return this.str; 84 } 85 86 89 public void setString(String str) { 90 if (null == str) { 91 throw new IllegalArgumentException ("StringNode: str is null"); 92 } 93 this.str = str; 94 } 95 96 public boolean equals(Object o) { 97 if (!(o instanceof StringNode)) { return false; } 98 return o instanceof StringNode 99 && this.str.equals(((StringNode) o).str); 100 } 101 102 private String str; 103 } 104 105 public Node(int nodeType) { 106 type = nodeType; 107 } 108 109 public Node(int nodeType, Node child) { 110 type = nodeType; 111 first = last = child; 112 child.next = null; 113 } 114 115 public Node(int nodeType, Node left, Node right) { 116 type = nodeType; 117 first = left; 118 last = right; 119 left.next = right; 120 right.next = null; 121 } 122 123 public Node(int nodeType, Node left, Node mid, Node right) { 124 type = nodeType; 125 first = left; 126 last = right; 127 left.next = mid; 128 mid.next = right; 129 right.next = null; 130 } 131 132 public Node(int nodeType, Node left, Node mid, Node mid2, Node right) { 133 type = nodeType; 134 first = left; 135 last = right; 136 left.next = mid; 137 mid.next = mid2; 138 mid2.next = right; 139 right.next = null; 140 } 141 142 public Node(int nodeType, Node[] children) { 143 this.type = nodeType; 144 if (children.length != 0) { 145 this.first = children[0]; 146 this.last = children[children.length - 1]; 147 148 for (int i = 1; i < children.length; i++) { 149 if (null != children[i - 1].next) { 150 throw new IllegalArgumentException ("duplicate child"); 152 } 153 children[i - 1].next = children[i]; 154 } 155 if (null != this.last.next) { 156 throw new IllegalArgumentException ("duplicate child"); 158 } 159 } 160 } 161 162 public Node(int nodeType, int value) { 163 type = nodeType; 164 intDatum = value; 165 } 166 167 public Node(int nodeType, Node child, int value) { 168 this(nodeType, child); 169 intDatum = value; 170 } 171 172 public Node(int nodeType, Node left, Node right, int value) { 173 this(nodeType, left, right); 174 intDatum = value; 175 } 176 177 public Node(int nodeType, Node left, Node mid, Node right, int value) { 178 this(nodeType, left, mid, right); 179 intDatum = value; 180 } 181 182 public static Node newNumber(double number) { 183 return new NumberNode(number); 184 } 185 186 public static Node newString(String str) { 187 return new StringNode(TokenStream.STRING, str); 188 } 189 190 public static Node newString(int type, String str) { 191 return new StringNode(type, str); 192 } 193 194 public int getType() { 195 return type; 196 } 197 198 public void setType(int type) { 199 this.type = type; 200 } 201 202 public int getIntDatum() { 203 return this.intDatum; 204 } 205 206 public boolean hasChildren() { 207 return first != null; 208 } 209 210 public Node getFirstChild() { 211 return first; 212 } 213 214 public Node getLastChild() { 215 return last; 216 } 217 218 public Node getNext() { 219 return next; 220 } 221 222 public int getChildCount() { 223 int c = 0; 224 for (Node n = first; n != null; n = n.next) 225 c++; 226 227 return c; 228 } 229 230 231 public Node getChildBefore(Node child) { 232 if (child == first) 233 return null; 234 Node n = first; 235 while (n.next != child) { 236 n = n.next; 237 if (n == null) 238 throw new RuntimeException ("node is not a child"); 239 } 240 return n; 241 } 242 243 public Node getLastSibling() { 244 Node n = this; 245 while (n.next != null) { 246 n = n.next; 247 } 248 return n; 249 } 250 251 public void addChildToFront(Node child) { 252 child.next = first; 253 first = child; 254 if (last == null) { 255 last = child; 256 } 257 } 258 259 public void addChildToBack(Node child) { 260 child.next = null; 261 if (last == null) { 262 first = last = child; 263 return; 264 } 265 last.next = child; 266 last = child; 267 } 268 269 public void addChildrenToFront(Node children) { 270 Node lastSib = children.getLastSibling(); 271 lastSib.next = first; 272 first = children; 273 if (last == null) { 274 last = lastSib; 275 } 276 } 277 278 public void addChildrenToBack(Node children) { 279 if (last != null) { 280 last.next = children; 281 } 282 last = children.getLastSibling(); 283 if (first == null) { 284 first = children; 285 } 286 } 287 288 291 public void addChildBefore(Node newChild, Node node) { 292 if (newChild.next != null) 293 throw new RuntimeException ( 294 "newChild had siblings in addChildBefore"); 295 if (first == node) { 296 newChild.next = first; 297 first = newChild; 298 return; 299 } 300 Node prev = getChildBefore(node); 301 addChildAfter(newChild, prev); 302 } 303 304 307 public void addChildAfter(Node newChild, Node node) { 308 if (newChild.next != null) 309 throw new RuntimeException ( 310 "newChild had siblings in addChildAfter"); 311 newChild.next = node.next; 312 node.next = newChild; 313 if (last == node) 314 last = newChild; 315 } 316 317 public void removeChild(Node child) { 318 Node prev = getChildBefore(child); 319 if (prev == null) 320 first = first.next; 321 else 322 prev.next = child.next; 323 if (child == last) last = prev; 324 child.next = null; 325 } 326 327 public void replaceChild(Node child, Node newChild) { 328 newChild.next = child.next; 329 if (child == first) { 330 first = newChild; 331 } else { 332 Node prev = getChildBefore(child); 333 prev.next = newChild; 334 } 335 if (child == last) 336 last = newChild; 337 child.next = null; 338 } 339 340 public void replaceChildAfter(Node prevChild, Node newChild) { 341 Node child = prevChild.next; 342 newChild.next = child.next; 343 prevChild.next = newChild; 344 if (child == last) 345 last = newChild; 346 child.next = null; 347 } 348 349 public static final int 350 TARGET_PROP = 1, 351 BREAK_PROP = 2, 352 CONTINUE_PROP = 3, 353 ENUM_PROP = 4, 354 FUNCTION_PROP = 5, 355 TEMP_PROP = 6, 356 LOCAL_PROP = 7, 357 CODEOFFSET_PROP = 8, 358 FIXUPS_PROP = 9, 359 VARS_PROP = 10, 360 USES_PROP = 11, 361 REGEXP_PROP = 12, 362 CASES_PROP = 13, 363 DEFAULT_PROP = 14, 364 CASEARRAY_PROP = 15, 365 SOURCENAME_PROP = 16, 366 SOURCE_PROP = 17, 367 TYPE_PROP = 18, 368 SPECIAL_PROP_PROP = 19, 369 LABEL_PROP = 20, 370 FINALLY_PROP = 21, 371 LOCALCOUNT_PROP = 22, 372 385 386 TARGETBLOCK_PROP = 23, 387 VARIABLE_PROP = 24, 388 LASTUSE_PROP = 25, 389 ISNUMBER_PROP = 26, 390 DIRECTCALL_PROP = 27, 391 392 BASE_LINENO_PROP = 28, 393 END_LINENO_PROP = 29, 394 SPECIALCALL_PROP = 30, 395 DEBUGSOURCE_PROP = 31; 396 397 public static final int BOTH = 0, LEFT = 1, 400 RIGHT = 2; 401 402 private static final String propToString(int propType) { 403 switch (propType) { 404 case TARGET_PROP: return "target"; 405 case BREAK_PROP: return "break"; 406 case CONTINUE_PROP: return "continue"; 407 case ENUM_PROP: return "enum"; 408 case FUNCTION_PROP: return "function"; 409 case TEMP_PROP: return "temp"; 410 case LOCAL_PROP: return "local"; 411 case CODEOFFSET_PROP: return "codeoffset"; 412 case FIXUPS_PROP: return "fixups"; 413 case VARS_PROP: return "vars"; 414 case USES_PROP: return "uses"; 415 case REGEXP_PROP: return "regexp"; 416 case CASES_PROP: return "cases"; 417 case DEFAULT_PROP: return "default"; 418 case CASEARRAY_PROP: return "casearray"; 419 case SOURCENAME_PROP: return "sourcename"; 420 case SOURCE_PROP: return "source"; 421 case TYPE_PROP: return "type"; 422 case SPECIAL_PROP_PROP: return "special_prop"; 423 case LABEL_PROP: return "label"; 424 case FINALLY_PROP: return "finally"; 425 case LOCALCOUNT_PROP: return "localcount"; 426 427 case TARGETBLOCK_PROP: return "targetblock"; 428 case VARIABLE_PROP: return "variable"; 429 case LASTUSE_PROP: return "lastuse"; 430 case ISNUMBER_PROP: return "isnumber"; 431 case DIRECTCALL_PROP: return "directcall"; 432 433 case BASE_LINENO_PROP: return "base_lineno"; 434 case END_LINENO_PROP: return "end_lineno"; 435 case SPECIALCALL_PROP: return "specialcall"; 436 case DEBUGSOURCE_PROP: return "debugsource"; 437 438 default: Context.codeBug(); 439 440 } 441 return null; 442 } 443 444 public Object getProp(int propType) { 445 if (props == null) 446 return null; 447 return props.getObject(propType); 448 } 449 450 public int getIntProp(int propType, int defaultValue) { 451 if (props == null) 452 return defaultValue; 453 return props.getInt(propType, defaultValue); 454 } 455 456 public int getExistingIntProp(int propType) { 457 return props.getExistingInt(propType); 458 } 459 460 public void putProp(int propType, Object prop) { 461 if (prop == null) { 462 removeProp(propType); 463 } 464 else { 465 if (props == null) { 466 props = new UintMap(2); 467 } 468 props.put(propType, prop); 469 } 470 } 471 472 public void putIntProp(int propType, int prop) { 473 if (props == null) 474 props = new UintMap(2); 475 props.put(propType, prop); 476 } 477 478 public void removeProp(int propType) { 479 if (props != null) { 480 props.remove(propType); 481 } 482 } 483 484 public int getOperation() { 485 switch (type) { 486 case TokenStream.EQOP: 487 case TokenStream.RELOP: 488 case TokenStream.UNARYOP: 489 case TokenStream.PRIMARY: 490 return intDatum; 491 } 492 Context.codeBug(); 493 return 0; 494 } 495 496 public int getLineno() { 497 if (hasLineno()) { 498 return intDatum; 499 } 500 return -1; 501 } 502 503 private boolean hasLineno() { 504 switch (type) { 505 case TokenStream.EXPRSTMT: 506 case TokenStream.BLOCK: 507 case TokenStream.VAR: 508 case TokenStream.WHILE: 509 case TokenStream.DO: 510 case TokenStream.SWITCH: 511 case TokenStream.CATCH: 512 case TokenStream.THROW: 513 case TokenStream.RETURN: 514 case TokenStream.BREAK: 515 case TokenStream.CONTINUE: 516 case TokenStream.WITH: 517 return true; 518 } 519 return false; 520 } 521 522 523 public double getDouble() throws UnsupportedOperationException { 524 throw new UnsupportedOperationException (this + " is not a number node"); 525 } 526 527 528 public String getString() throws UnsupportedOperationException { 529 throw new UnsupportedOperationException (this + " is not a string node"); 530 } 531 532 533 public void setString(String s) throws UnsupportedOperationException { 534 throw new UnsupportedOperationException (this + " is not a string node"); 535 } 536 537 public boolean equals(Object o) { 538 if (!(o instanceof Node)) { return false; } 539 return hasLineno() 540 || this.getIntDatum() == ((Node) o).getIntDatum(); 541 } 542 543 public Node cloneNode() { 544 Node result; 545 try { 546 result = (Node) super.clone(); 547 result.next = null; 548 result.first = null; 549 result.last = null; 550 } 551 catch (CloneNotSupportedException e) { 552 throw new RuntimeException (e.getMessage()); 553 } 554 return result; 555 } 556 557 public Node cloneTree() { 558 Node result = cloneNode(); 559 for (Node n2 = getFirstChild(); n2 != null; n2 = n2.getNext()) { 560 Node n2clone = n2.cloneTree(); 561 if (result.last != null) { 562 result.last.next = n2clone; 563 } 564 if (result.first == null) { 565 result.first = n2clone; 566 } 567 result.last = n2clone; 568 } 569 return result; 570 } 571 572 573 574 public String toString() { 575 if (Context.printTrees) { 576 StringBuffer sb = new StringBuffer (TokenStream.tokenToName(type)); 577 if (this instanceof StringNode) { 578 sb.append(' '); 579 sb.append(getString()); 580 } else { 581 switch (type) { 582 case TokenStream.TARGET: 583 sb.append(' '); 584 sb.append(hashCode()); 585 break; 586 case TokenStream.NUMBER: 587 sb.append(' '); 588 sb.append(getDouble()); 589 break; 590 case TokenStream.FUNCTION: 591 sb.append(' '); 592 sb.append(first.getString()); 593 break; 594 } 595 } 596 if (intDatum != -1) { 597 sb.append(' '); 598 sb.append(intDatum); 599 } 600 if (props == null) 601 return sb.toString(); 602 603 int[] keys = props.getKeys(); 604 for (int i = 0; i != keys.length; ++i) { 605 int key = keys[i]; 606 sb.append(" ["); 607 sb.append(propToString(key)); 608 sb.append(": "); 609 switch (key) { 610 case FIXUPS_PROP : sb.append("fixups property"); 612 break; 613 case SOURCE_PROP : sb.append("source property"); 615 break; 616 case TARGETBLOCK_PROP : sb.append("target block property"); 618 break; 619 case LASTUSE_PROP : sb.append("last use property"); 621 break; 622 default : 623 Object obj = props.getObject(key); 624 if (obj != null) { 625 sb.append(obj.toString()); 626 } else { 627 sb.append(props.getExistingInt(key)); 628 } 629 break; 630 } 631 sb.append(']'); 632 } 633 return sb.toString(); 634 } 635 return null; 636 } 637 638 public String toStringTree() { 639 return toStringTreeHelper(0); 640 } 641 642 643 private String toStringTreeHelper(int level) { 644 if (Context.printTrees) { 645 StringBuffer s = new StringBuffer (); 646 for (int i=0; i < level; i++) { 647 s.append(" "); 648 } 649 s.append(toString()); 650 s.append('\n'); 651 for (Node cursor = getFirstChild(); cursor != null; 652 cursor = cursor.getNext()) 653 { 654 Node n = cursor; 655 s.append(n.toStringTreeHelper(level+1)); 656 } 657 return s.toString(); 658 } 659 return ""; 660 } 661 662 666 public String checkTreeEquals(Node node2) { 667 boolean eq = false; 668 669 if (type == node2.getType() && 670 getChildCount() == node2.getChildCount() && 671 getClass() == node2.getClass()) { 672 673 eq = this.equals(node2); 674 } 675 676 if (!eq) { 677 return "Node tree inequality:\nTree1:\n" + toStringTreeHelper(1) + 678 "\n\nTree2:\n" + node2.toStringTreeHelper(1); 679 } 680 681 String res = null; 682 Node n, n2; 683 for (n = first, n2 = node2.first; 684 res == null && n != null; 685 n = n.next, n2 = n2.next) { 686 res = n.checkTreeEquals(n2); 687 if (res != null) { 688 return res; 689 } 690 } 691 return res; 692 } 693 694 public void setIsSyntheticBlock(boolean val) { 695 isSyntheticBlock = val; 696 } 697 698 public boolean isSyntheticBlock() { 699 return isSyntheticBlock; 700 } 701 702 int type; Node next; private Node first; private Node last; private int intDatum = -1; private UintMap props; 708 private boolean isSyntheticBlock = false; 709 } 710 | Popular Tags |