1 package polyglot.visit; 2 3 import java.util.*; 4 5 import polyglot.ast.*; 6 import polyglot.frontend.Job; 7 import polyglot.main.Report; 8 import polyglot.types.SemanticException; 9 import polyglot.types.Type; 10 import polyglot.types.TypeSystem; 11 import polyglot.util.IdentityKey; 12 import polyglot.util.InternalCompilerError; 13 import polyglot.util.StringUtil; 14 import polyglot.visit.FlowGraph.Edge; 15 import polyglot.visit.FlowGraph.EdgeKey; 16 import polyglot.visit.FlowGraph.ExceptionEdgeKey; 17 import polyglot.visit.FlowGraph.Peer; 18 19 23 public abstract class DataFlow extends ErrorHandlingVisitor 24 { 25 28 protected final boolean forward; 29 30 40 protected final boolean dataflowOnEntry; 41 42 50 protected LinkedList flowgraphStack; 51 52 protected static class FlowGraphSource { 53 FlowGraphSource(FlowGraph g, CodeDecl s) { 54 flowgraph = g; 55 source = s; 56 } 57 FlowGraph flowgraph; 58 CodeDecl source; 59 public FlowGraph flowGraph() { return flowgraph; } 60 public CodeDecl source() { return source; } 61 } 62 63 66 public DataFlow(Job job, TypeSystem ts, NodeFactory nf, boolean forward) { 67 this(job, ts, nf, forward, false); 68 } 69 70 73 public DataFlow(Job job, 74 TypeSystem ts, 75 NodeFactory nf, 76 boolean forward, 77 boolean dataflowOnEntry) { 78 super(job, ts, nf); 79 this.forward = forward; 80 this.dataflowOnEntry = dataflowOnEntry; 81 if (dataflowOnEntry) 82 this.flowgraphStack = new LinkedList(); 83 else 84 this.flowgraphStack = null; 85 } 86 87 99 public static abstract class Item { 100 public abstract boolean equals(Object i); 101 public abstract int hashCode(); 102 } 103 104 111 protected abstract Item createInitialItem(FlowGraph graph, Term node); 112 113 128 protected Map flow(Item in, FlowGraph graph, Term n, Set edgeKeys) { 129 throw new InternalCompilerError("Unimplemented: should be " + 130 "implemented by subclasses if " + 131 "needed"); 132 } 133 134 153 protected Map flow(List inItems, List inItemKeys, FlowGraph graph, Term n, Set edgeKeys) { 154 Item inItem = this.safeConfluence(inItems, inItemKeys, n, graph); 155 156 return this.flow(inItem, graph, n, edgeKeys); 157 } 158 159 160 161 162 182 protected final Map flowToBooleanFlow(List inItems, List inItemKeys, FlowGraph graph, Term n, Set edgeKeys) { 183 List trueItems = new ArrayList(); 184 List trueItemKeys = new ArrayList(); 185 List falseItems = new ArrayList(); 186 List falseItemKeys = new ArrayList(); 187 List otherItems = new ArrayList(); 188 List otherItemKeys = new ArrayList(); 189 190 Iterator i = inItems.iterator(); 191 Iterator j = inItemKeys.iterator(); 192 while (i.hasNext() || j.hasNext()) { 193 Item item = (Item)i.next(); 194 EdgeKey key = (EdgeKey)j.next(); 195 196 if (FlowGraph.EDGE_KEY_TRUE.equals(key)) { 197 trueItems.add(item); 198 trueItemKeys.add(key); 199 } 200 else if (FlowGraph.EDGE_KEY_FALSE.equals(key)) { 201 falseItems.add(item); 202 falseItemKeys.add(key); 203 } 204 else { 205 otherItems.add(item); 206 otherItemKeys.add(key); 207 } 208 } 209 210 Item trueItem = trueItems.isEmpty() ? null : this.safeConfluence(trueItems, trueItemKeys, n, graph); 211 Item falseItem = falseItems.isEmpty() ? null : this.safeConfluence(falseItems, falseItemKeys, n, graph); 212 Item otherItem = otherItems.isEmpty() ? null : this.safeConfluence(otherItems, otherItemKeys, n, graph); 213 214 return this.flow(trueItem, falseItem, otherItem, graph, n, edgeKeys); 215 } 216 217 protected Map flow(Item trueItem, Item falseItem, Item otherItem, 218 FlowGraph graph, Term n, Set edgeKeys) { 219 throw new InternalCompilerError("Unimplemented: should be " + 220 "implemented by subclasses if " + 221 "needed"); 222 } 223 224 232 protected Map flowBooleanConditions(Item trueItem, Item falseItem, Item otherItem, 233 FlowGraph graph, Expr n, Set edgeKeys) { 234 if (!n.type().isBoolean() || !(n instanceof Binary || n instanceof Unary)) { 235 throw new InternalCompilerError("This method only takes binary " + 236 "or unary operators of boolean type"); 237 } 238 239 if (trueItem == null || falseItem == null) { 240 throw new IllegalArgumentException ("The trueItem and falseItem " + 241 "for flowBooleanConditions must be non-null."); 242 } 243 244 if (n instanceof Unary) { 245 Unary u = (Unary)n; 246 if (u.operator() == Unary.NOT) { 247 return itemsToMap(falseItem, trueItem, otherItem, edgeKeys); 248 } 249 } 250 else { 251 Binary b = (Binary)n; 252 if (b.operator() == Binary.COND_AND) { 253 return itemsToMap(trueItem, falseItem, otherItem, edgeKeys); 256 } 257 else if (b.operator() == Binary.COND_OR) { 258 return itemsToMap(trueItem, falseItem, otherItem, edgeKeys); 261 } 262 else if (b.operator() == Binary.BIT_AND) { 263 Item bitANDFalse = 267 this.safeConfluence(trueItem, FlowGraph.EDGE_KEY_TRUE, 268 falseItem, FlowGraph.EDGE_KEY_FALSE, 269 n, graph); 270 return itemsToMap(trueItem, bitANDFalse, otherItem, edgeKeys); 271 } 272 else if (b.operator() == Binary.BIT_OR) { 273 Item bitORTrue = 277 this.safeConfluence(trueItem, FlowGraph.EDGE_KEY_TRUE, 278 falseItem, FlowGraph.EDGE_KEY_FALSE, 279 n, graph); 280 return itemsToMap(bitORTrue, falseItem, otherItem, edgeKeys); 281 } 282 } 283 return null; 284 } 285 286 298 protected abstract Item confluence(List items, Term node, FlowGraph graph); 299 300 315 protected Item confluence(List items, List itemKeys, Term node, FlowGraph graph) { 316 return confluence(items, node, graph); 317 } 318 319 334 protected Item safeConfluence(List items, List itemKeys, Term node, FlowGraph graph) { 335 if (items.isEmpty()) { 336 return this.createInitialItem(graph, node); 337 } 338 if (items.size() == 1) { 339 return (Item)items.get(0); 340 } 341 return confluence(items, itemKeys, node, graph); 342 } 343 344 protected Item safeConfluence(Item item1, FlowGraph.EdgeKey key1, 345 Item item2, FlowGraph.EdgeKey key2, 346 Term node, FlowGraph graph) { 347 return safeConfluence(item1, key1, item2, key2, null, null, node, graph); 348 } 349 350 protected Item safeConfluence(Item item1, FlowGraph.EdgeKey key1, 351 Item item2, FlowGraph.EdgeKey key2, 352 Item item3, FlowGraph.EdgeKey key3, 353 Term node, FlowGraph graph) { 354 List items = new ArrayList(3); 355 List itemKeys = new ArrayList(3); 356 357 if (item1 != null) { 358 items.add(item1); 359 itemKeys.add(key1); 360 } 361 if (item2 != null) { 362 items.add(item2); 363 itemKeys.add(key2); 364 } 365 if (item3 != null) { 366 items.add(item3); 367 itemKeys.add(key3); 368 } 369 return safeConfluence(items, itemKeys, node, graph); 370 } 371 372 381 protected abstract void check(FlowGraph graph, Term n, Item inItem, Map outItems) throws SemanticException; 382 383 391 protected void dataflow(CodeDecl cd) throws SemanticException { 392 if (cd.body() != null) { 394 FlowGraph g = initGraph(cd, cd); 396 397 if (g != null) { 398 CFGBuilder v = createCFGBuilder(ts, g); 400 401 try { 402 v.visitGraph(); 403 } 404 catch (CFGBuildError e) { 405 throw new SemanticException(e.message(), e.position()); 406 } 407 408 dataflow(g); 409 410 post(g, cd); 411 412 if (dataflowOnEntry) 414 flowgraphStack.addFirst(new FlowGraphSource(g, cd)); 415 } 416 } 417 } 418 419 420 static private class Frame { 421 Peer peer; 422 Iterator edges; 423 Frame(Peer p, boolean forward) { 424 peer = p; 425 if (forward) edges = p.succs().iterator(); 426 else edges = p.preds().iterator(); 427 } 428 } 429 430 436 protected LinkedList findSCCs(FlowGraph graph) { 437 Collection peers = graph.peers(); 438 Peer[] sorted = new Peer[peers.size()]; 439 Collection start = graph.peers(graph.startNode()); 440 443 445 int n = 0; 447 LinkedList stack = new LinkedList(); 448 Set reachable = new HashSet(); 449 for (Iterator i = start.iterator(); i.hasNext(); ) { 450 Peer peer = (Peer)i.next(); 451 if (!reachable.contains(peer)) { 452 reachable.add(peer); 453 stack.addFirst(new Frame(peer, true)); 454 while (stack.size() != 0) { 455 Frame top = (Frame)stack.getFirst(); 456 if (top.edges.hasNext()) { 457 Edge e = (Edge)top.edges.next(); 458 Peer q = e.getTarget(); 459 if (!reachable.contains(q)) { 460 reachable.add(q); 461 stack.addFirst(new Frame(q, true)); 462 } 463 } else { 464 stack.removeFirst(); 465 sorted[n++] = top.peer; 466 } 467 } 468 } 469 } 470 Peer[] by_scc = new Peer[n]; 475 int[] scc_head = new int[n]; 476 Set visited = new HashSet(); 477 int head = 0; 478 for (int i=n-1; i>=0; i--) { 479 if (!visited.contains(sorted[i])) { 480 Set SCC = new HashSet(); 482 visited.add(sorted[i]); 483 stack.add(new Frame(sorted[i], false)); 484 while (stack.size() != 0) { 485 Frame top = (Frame)stack.getFirst(); 486 if (top.edges.hasNext()) { 487 Edge e = (Edge)top.edges.next(); 488 Peer q = e.getTarget(); 489 if (reachable.contains(q) && !visited.contains(q)) { 490 visited.add(q); 491 Frame f = new Frame(q, false); 492 stack.addFirst(f); 493 } 494 } else { 495 stack.removeFirst(); 496 SCC.add(top.peer); 497 } 498 } 499 stack.add(new Frame(sorted[i], true)); 502 Set revisited = new HashSet(); 503 revisited.add(sorted[i]); 504 int scc_size = SCC.size(); 505 int nsorted = 0; 506 while (stack.size() != 0) { 507 Frame top = (Frame)stack.getFirst(); 508 if (top.edges.hasNext()) { 509 Edge e = (Edge)top.edges.next(); 510 Peer q = e.getTarget(); 511 if (SCC.contains(q) && !revisited.contains(q)) { 512 revisited.add(q); 513 Frame f = new Frame(q, true); 514 stack.addFirst(f); 515 } 516 } else { 517 stack.removeFirst(); 518 int n3 = head + scc_size - nsorted - 1; 519 scc_head[n3] = -2; 520 by_scc[n3] = top.peer; 521 nsorted++; 522 } 523 } 524 scc_head[head+scc_size-1] = head; 525 scc_head[head] = -1; 526 head = head + scc_size; 527 } 528 } 529 if (Report.should_report(Report.dataflow, 2)) { 530 for (int j = 0; j < n; j++) { 531 switch(scc_head[j]) { 532 case -1: Report.report(2, j + "[HEAD] : " + by_scc[j]); break; 533 case -2: Report.report(2, j + " : " + by_scc[j]); break; 534 default: Report.report(2, j + " ->"+ scc_head[j] + " : " + by_scc[j]); 535 } 536 for (Iterator i = by_scc[j].succs().iterator(); i.hasNext(); ) { 537 Report.report(3, " successor: " + ((Edge)i.next()).getTarget()); 538 } 539 } 540 } 541 LinkedList ret = new LinkedList(); 542 ret.addFirst(scc_head); 543 ret.addFirst(by_scc); 544 return ret; 545 } 546 547 550 protected void dataflow(FlowGraph graph) { 551 if (Report.should_report(Report.dataflow, 1)) { 552 Report.report(1, "Finding strongly connected components"); 553 } 554 LinkedList pair = findSCCs(graph); 555 Peer[] by_scc = (Peer[])pair.getFirst(); 556 int[] scc_head = (int[])pair.getLast(); 557 int npeers = by_scc.length; 558 559 564 if (Report.should_report(Report.dataflow, 1)) { 565 Report.report(1, "Iterating dataflow equations"); 566 } 567 568 int current = 0; 569 boolean change = false; 570 571 while (current < npeers) { 572 Peer p = by_scc[current]; 573 if (scc_head[current] == -1) { 574 change = false; } 576 577 List inItems = new ArrayList(p.preds.size()); 580 List inItemKeys = new ArrayList(p.preds.size()); 581 for (Iterator i = p.preds.iterator(); i.hasNext(); ) { 582 Edge e = (Edge)i.next(); 583 Peer o = e.getTarget(); 584 if (o.outItems != null) { 585 if (!o.outItems.keySet().contains(e.getKey())) { 586 throw new InternalCompilerError("There should have " + 587 "an out Item with edge key " + e.getKey() + 588 "; instead there were only " + 589 o.outItems.keySet()); 590 } 591 Item it = (Item)o.outItems.get(e.getKey()); 592 if (it != null) { 593 inItems.add(it); 594 inItemKeys.add(e.getKey()); 595 } 596 } 597 } 598 599 Map oldOutItems = p.outItems; 601 p.inItem = this.safeConfluence(inItems, inItemKeys, p.node, graph); 602 p.outItems = this.flow(inItems, inItemKeys, graph, p.node, p.succEdgeKeys()); 603 604 if (!p.succEdgeKeys().equals(p.outItems.keySet())) { 605 throw new InternalCompilerError("The flow only defined " + 609 "outputs for " + p.outItems.keySet() + "; needs to " + 610 "define outputs for all of: " + p.succEdgeKeys()); 611 } 612 613 if (oldOutItems != p.outItems && 614 (oldOutItems == null || !oldOutItems.equals(p.outItems))) { 615 change = true; 618 } 619 if (change && scc_head[current] >= 0) { 620 current = scc_head[current]; 622 } else { 623 current++; 624 } 625 } 626 if (Report.should_report(Report.dataflow, 1)) { 627 Report.report(1, "Done."); 628 } 629 } 630 631 639 protected FlowGraph initGraph(CodeDecl code, Term root) { 640 return new FlowGraph(root, forward); 641 } 642 643 650 protected CFGBuilder createCFGBuilder(TypeSystem ts, FlowGraph g) { 651 return new CFGBuilder(ts, g, this); 652 } 653 654 658 protected NodeVisitor enterCall(Node n) throws SemanticException { 659 if (dataflowOnEntry && n instanceof CodeDecl) { 660 dataflow((CodeDecl)n); 661 } 662 663 return this; 664 } 665 666 671 public Node leave(Node parent, Node old, Node n, NodeVisitor v) { 672 if (old != n) { 673 if (dataflowOnEntry && currentFlowGraph() != null) { 674 Object o = currentFlowGraph().peerMap.get(new IdentityKey(old)); 678 if (o != null) { 679 currentFlowGraph().peerMap.put(new IdentityKey(n), o); 680 } 681 } 682 } 683 return super.leave(parent, old, n, v); 684 } 685 686 690 protected Node leaveCall(Node n) throws SemanticException { 691 if (n instanceof CodeDecl) { 692 if (!dataflowOnEntry) { 693 dataflow((CodeDecl)n); 694 } 695 else if (dataflowOnEntry && !flowgraphStack.isEmpty()) { 696 FlowGraphSource fgs = (FlowGraphSource)flowgraphStack.getFirst(); 697 if (fgs.source.equals(n)) { 698 flowgraphStack.removeFirst(); 701 } 702 } 703 } 704 return n; 705 } 706 707 711 protected void post(FlowGraph graph, Term root) throws SemanticException { 712 if (Report.should_report(Report.cfg, 2)) { 713 dumpFlowGraph(graph, root); 714 } 715 716 Set uncheckedPeers = new HashSet(graph.peers()); 718 LinkedList peersToCheck = new LinkedList(graph.peers(graph.startNode())); 719 while (!peersToCheck.isEmpty()) { 720 Peer p = (Peer) peersToCheck.removeFirst(); 721 uncheckedPeers.remove(p); 722 723 this.check(graph, p.node, p.inItem, p.outItems); 724 725 for (Iterator iter = p.succs.iterator(); iter.hasNext(); ) { 726 Peer q = ((Edge)iter.next()).getTarget(); 727 if (uncheckedPeers.contains(q) && !peersToCheck.contains(q)) { 728 peersToCheck.addLast(q); 730 } 731 } 732 733 if (peersToCheck.isEmpty() && !uncheckedPeers.isEmpty()) { 734 Iterator i = uncheckedPeers.iterator(); 736 peersToCheck.add(i.next()); 737 i.remove(); 738 } 739 740 } 741 } 742 743 754 protected FlowGraph currentFlowGraph() { 755 if (!dataflowOnEntry) { 756 throw new InternalCompilerError("currentFlowGraph() cannot be" + 757 " called when dataflow is not performed on entry"); 758 } 759 if (flowgraphStack.isEmpty()) { 760 return null; 761 } 762 return ((FlowGraphSource)flowgraphStack.getFirst()).flowgraph; 763 } 764 765 781 protected static final Map itemToMap(Item i, Set edgeKeys) { 782 Map m = new HashMap(); 783 for (Iterator iter = edgeKeys.iterator(); iter.hasNext(); ) { 784 Object o = iter.next(); 785 m.put(o, i); 786 } 787 return m; 788 } 789 790 815 protected static final Map itemsToMap(Item trueItem, Item falseItem, Item remainingItem, Set edgeKeys) { 816 Map m = new HashMap(); 817 818 for (Iterator iter = edgeKeys.iterator(); iter.hasNext(); ) { 819 FlowGraph.EdgeKey k = (EdgeKey)iter.next(); 820 if (FlowGraph.EDGE_KEY_TRUE.equals(k)) { 821 m.put(k, trueItem); 822 } 823 else if (FlowGraph.EDGE_KEY_FALSE.equals(k)) { 824 m.put(k, falseItem); 825 } 826 else { 827 m.put(k, remainingItem); 828 } 829 } 830 return m; 831 } 832 833 847 protected final List filterItemsNonError(List items, List itemKeys) { 848 List filtered = new ArrayList(items.size()); 849 Iterator i = items.iterator(); 850 Iterator j = itemKeys.iterator(); 851 while (i.hasNext() && j.hasNext()) { 852 Item item = (Item)i.next(); 853 EdgeKey key = (EdgeKey)j.next(); 854 855 if (!(key instanceof ExceptionEdgeKey && 856 ((ExceptionEdgeKey)key).type().isSubtype(ts.Error()))) { 857 filtered.add(item); 859 } 860 } 861 862 if (i.hasNext() || j.hasNext()) { 863 throw new InternalCompilerError("item and item key lists " + 864 "have different sizes."); 865 } 866 867 return filtered; 868 } 869 870 882 protected final List filterItemsNonException(List items, List itemKeys) { 883 List filtered = new ArrayList(items.size()); 884 Iterator i = items.iterator(); 885 Iterator j = itemKeys.iterator(); 886 while (i.hasNext() && j.hasNext()) { 887 Item item = (Item)i.next(); 888 EdgeKey key = (EdgeKey)j.next(); 889 890 if (!(key instanceof ExceptionEdgeKey)) { 891 filtered.add(item); 893 } 894 } 895 896 if (i.hasNext() || j.hasNext()) { 897 throw new InternalCompilerError("item and item key lists " + 898 "have different sizes."); 899 } 900 901 return filtered; 902 } 903 904 919 protected final List filterItemsExceptionSubclass(List items, List itemKeys, Type excType) { 920 List filtered = new ArrayList(items.size()); 921 Iterator i = items.iterator(); 922 Iterator j = itemKeys.iterator(); 923 while (i.hasNext() && j.hasNext()) { 924 Item item = (Item)i.next(); 925 EdgeKey key = (EdgeKey)j.next(); 926 927 if (key instanceof ExceptionEdgeKey) { 928 ExceptionEdgeKey eek = (ExceptionEdgeKey)key; 930 if (eek.type().isImplicitCastValid(excType)) { 931 filtered.add(item); 932 } 933 } 934 } 935 936 if (i.hasNext() || j.hasNext()) { 937 throw new InternalCompilerError("item and item key lists " + 938 "have different sizes."); 939 } 940 941 return filtered; 942 } 943 944 955 protected final List filterItems(List items, List itemKeys, FlowGraph.EdgeKey filterEdgeKey) { 956 List filtered = new ArrayList(items.size()); 957 Iterator i = items.iterator(); 958 Iterator j = itemKeys.iterator(); 959 while (i.hasNext() && j.hasNext()) { 960 Item item = (Item)i.next(); 961 EdgeKey key = (EdgeKey)j.next(); 962 963 if (filterEdgeKey.equals(key)) { 964 filtered.add(item); 966 } 967 } 968 969 if (i.hasNext() || j.hasNext()) { 970 throw new InternalCompilerError("item and item key lists " + 971 "have different sizes."); 972 } 973 974 return filtered; 975 } 976 977 978 991 protected static final boolean hasTrueFalseBranches(Set edgeKeys) { 992 return edgeKeys.contains(FlowGraph.EDGE_KEY_FALSE) && 993 edgeKeys.contains(FlowGraph.EDGE_KEY_TRUE); 994 } 995 996 1022 protected static Map constructItemsFromCondition(Expr booleanCond, 1023 Item startingItem, 1024 Set succEdgeKeys, 1025 ConditionNavigator navigator) { 1026 if (!booleanCond.type().isBoolean()) { 1028 throw new IllegalArgumentException ("booleanCond must be a boolean expression"); 1029 } 1030 if (!hasTrueFalseBranches(succEdgeKeys)) { 1031 throw new IllegalArgumentException ("succEdgeKeys does not have true and false branches."); 1032 } 1033 1034 1035 BoolItem results = navigator.navigate(booleanCond, startingItem); 1036 1037 Map m = new HashMap(); 1038 m.put(FlowGraph.EDGE_KEY_TRUE, results.trueItem); 1039 m.put(FlowGraph.EDGE_KEY_FALSE, results.falseItem); 1040 1041 for (Iterator iter = succEdgeKeys.iterator(); iter.hasNext(); ) { 1044 EdgeKey e = (EdgeKey)iter.next(); 1045 if (!FlowGraph.EDGE_KEY_TRUE.equals(e) && 1046 !FlowGraph.EDGE_KEY_FALSE.equals(e)) { 1047 m.put(e, startingItem); 1048 } 1049 } 1050 1051 return m; 1052 } 1053 1054 1060 protected static class BoolItem { 1061 public BoolItem(Item trueItem, Item falseItem) { 1062 this.trueItem = trueItem; 1063 this.falseItem = falseItem; 1064 } 1065 Item trueItem; 1066 Item falseItem; 1067 public Item trueItem() { return trueItem; } 1068 public Item falseItem() { return falseItem; } 1069 public String toString() { 1070 return "[ true: " + trueItem + "; false: " + falseItem + " ]"; 1071 } 1072 1073 } 1074 1075 1091 protected abstract static class ConditionNavigator { 1092 1101 public BoolItem navigate(Expr expr, Item startingItem) { 1102 if (expr.type().isBoolean()) { 1103 if (expr instanceof Binary) { 1104 Binary b = (Binary)expr; 1105 if (Binary.COND_AND.equals(b.operator()) || 1106 Binary.BIT_AND.equals(b.operator())) { 1107 1108 BoolItem leftRes = navigate(b.left(), startingItem); 1109 Item rightResStart = startingItem; 1110 if (Binary.COND_AND.equals(b.operator())) { 1111 rightResStart = leftRes.trueItem; 1115 } 1116 BoolItem rightRes = navigate(b.right(), rightResStart); 1117 return andResults(leftRes, rightRes, startingItem); 1118 } 1119 else if (Binary.COND_OR.equals(b.operator()) || 1120 Binary.BIT_OR.equals(b.operator())) { 1121 1122 BoolItem leftRes = navigate(b.left(), startingItem); 1123 Item rightResStart = startingItem; 1124 if (Binary.COND_OR.equals(b.operator())) { 1125 rightResStart = leftRes.falseItem; 1129 } 1130 BoolItem rightRes = navigate(b.right(), rightResStart); 1131 return orResults(leftRes, rightRes, startingItem); 1132 } 1133 } 1134 else if (expr instanceof Unary) { 1135 Unary u = (Unary)expr; 1136 if (Unary.NOT.equals(u.operator())) { 1137 BoolItem res = navigate(u.expr(), startingItem); 1138 return notResult(res); 1139 } 1140 } 1141 1142 } 1143 1144 return handleExpression(expr, startingItem); 1147 } 1148 1149 1153 public BoolItem andResults(BoolItem left, 1154 BoolItem right, 1155 Item startingItem) { 1156 return new BoolItem(combine(left.trueItem, right.trueItem), 1157 startingItem); 1158 } 1159 1160 1164 public BoolItem orResults(BoolItem left, 1165 BoolItem right, 1166 Item startingItem) { 1167 return new BoolItem(startingItem, 1168 combine(left.falseItem, right.falseItem)); 1169 } 1170 1171 1175 public BoolItem notResult(BoolItem results) { 1176 return new BoolItem(results.falseItem, results.trueItem); 1177 } 1178 1179 1186 public abstract Item combine(Item item1, Item item2); 1187 1188 1192 public abstract BoolItem handleExpression(Expr expr, Item startingItem); 1193 } 1194 1195 protected static int flowCounter = 0; 1196 1200 protected void dumpFlowGraph(FlowGraph graph, Term root) { 1201 String name = StringUtil.getShortNameComponent(this.getClass().getName()); 1202 name += flowCounter++; 1203 1204 String rootName = ""; 1205 if (graph.root() instanceof CodeDecl) { 1206 CodeDecl cd = (CodeDecl)graph.root(); 1207 rootName = cd.codeInstance().toString() + " in " + 1208 cd.codeInstance().container().toString(); 1209 } 1210 1211 1212 Report.report(2, "digraph DataFlow" + name + " {"); 1213 Report.report(2, " label=\"Dataflow: " + name + "\\n" + rootName + 1214 "\"; fontsize=20; center=true; ratio=auto; size = \"8.5,11\";"); 1215 1216 for (Iterator iter = graph.peers().iterator(); iter.hasNext(); ) { 1218 Peer p = (Peer)iter.next(); 1219 1220 Report.report(2, 1222 p.hashCode() + " [ label = \"" + 1223 StringUtil.escape(p.node.toString()) + "\\n(" + 1224 StringUtil.escape(StringUtil.getShortNameComponent(p.node.getClass().getName()))+ ")\" ];"); 1225 1226 for (Iterator iter2 = p.succs.iterator(); iter2.hasNext(); ) { 1228 Edge q = (Edge)iter2.next(); 1229 Report.report(2, 1230 q.getTarget().hashCode() + " [ label = \"" + 1231 StringUtil.escape(q.getTarget().node.toString()) + " (" + 1232 StringUtil.escape(StringUtil.getShortNameComponent(q.getTarget().node.getClass().getName()))+ ")\" ];"); 1233 String label = q.getKey().toString(); 1234 if (p.outItems != null) { 1235 label += "\\n" + p.outItems.get(q.getKey()); 1236 } 1237 else { 1238 label += "\\n[no dataflow available]"; 1239 } 1240 Report.report(2, p.hashCode() + " -> " + q.getTarget().hashCode() + 1241 " [label=\"" + label + "\"];"); 1242 } 1243 1244 } 1245 Report.report(2, "}"); 1246 } 1247} 1248 | Popular Tags |