| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE.md file. | |
| 4 | |
| 5 library fletchc.fletch_system_printer; | |
| 6 | |
| 7 import '../fletch_system.dart' show | |
| 8 FletchClass, | |
| 9 FletchFunction, | |
| 10 FletchSystem; | |
| 11 | |
| 12 import 'package:compiler/src/util/uri_extras.dart' show | |
| 13 relativize; | |
| 14 | |
| 15 import 'fletch_selector.dart' show | |
| 16 FletchSelector, | |
| 17 SelectorKind; | |
| 18 | |
| 19 import 'package:compiler/src/elements/elements.dart' show | |
| 20 Element, | |
| 21 CompilationUnitElement; | |
| 22 | |
| 23 class FletchSystemPrinter { | |
| 24 final FletchSystem system; | |
| 25 final Uri base; | |
| 26 final StringBuffer buffer = new StringBuffer(); | |
| 27 final String baseIndentation = " "; | |
| 28 | |
| 29 bool beginningOfLine = true; | |
| 30 | |
| 31 int indentationLevel = 0; | |
| 32 | |
| 33 FletchSystemPrinter(this.system, this.base); | |
| 34 | |
| 35 void indent() { | |
| 36 for (int i = 0; i < indentationLevel; i++) { | |
| 37 buffer.write(baseIndentation); | |
| 38 } | |
| 39 } | |
| 40 | |
| 41 void indented(f()) { | |
| 42 ++indentationLevel; | |
| 43 try { | |
| 44 f(); | |
| 45 } finally { | |
| 46 --indentationLevel; | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 void write(String text) { | |
| 51 if (beginningOfLine) { | |
| 52 indent(); | |
| 53 beginningOfLine = false; | |
| 54 } | |
| 55 buffer.write(text); | |
| 56 } | |
| 57 | |
| 58 void writeLine([String line = ""]) { | |
| 59 write("$line\n"); | |
| 60 beginningOfLine = true; | |
| 61 } | |
| 62 | |
| 63 void writeFletchFunctionAsBody(FletchFunction function) { | |
| 64 if (function.element != null) { | |
| 65 writeLine("=> ${function.element};"); | |
| 66 } else { | |
| 67 writeLine("{"); | |
| 68 indented(() { | |
| 69 for (String line in function.verboseToString().trim().split("\n")) { | |
| 70 writeLine("// $line"); | |
| 71 } | |
| 72 }); | |
| 73 writeLine("}"); | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 void writeMethodTableEntry( | |
| 78 DecodedFletchSelector selector, int functionId) { | |
| 79 switch (selector.kind) { | |
| 80 case SelectorKind.Method: | |
| 81 write("${selector.symbol}#${selector.arity}()"); | |
| 82 break; | |
| 83 | |
| 84 case SelectorKind.Getter: | |
| 85 assert(selector.arity == 0); | |
| 86 if (selector.symbol.startsWith("?is?")) { | |
| 87 writeLine("type test ${selector.symbol.substring(4)}"); | |
| 88 return; | |
| 89 } | |
| 90 write("get ${selector.symbol}"); | |
| 91 break; | |
| 92 | |
| 93 case SelectorKind.Setter: | |
| 94 assert(selector.arity == 1); | |
| 95 write("set ${selector.symbol}"); | |
| 96 break; | |
| 97 } | |
| 98 write(" "); | |
| 99 FletchFunction function = system.functionsById[functionId]; | |
| 100 writeFletchFunctionAsBody(function); | |
| 101 } | |
| 102 | |
| 103 void writeFletchClass(FletchClass cls, Set<FletchFunction> unseen) { | |
| 104 // TODO(ahe): Important if class is builtin or not. Information lost in | |
| 105 // FletchNewClassBuilder.finalizeClass. | |
| 106 if (cls.element != null) { | |
| 107 writeLine("class ${cls.element.name} {"); | |
| 108 } else { | |
| 109 writeLine("$cls {"); | |
| 110 } | |
| 111 indented(() { | |
| 112 Map<DecodedFletchSelector, int> methodTable = | |
| 113 <DecodedFletchSelector, int>{}; | |
| 114 for (var pair in cls.methodTable) { | |
| 115 DecodedFletchSelector selector = | |
| 116 new DecodedFletchSelector.fromEncodedSelector(pair.fst, system); | |
| 117 methodTable[selector] = pair.snd; | |
| 118 } | |
| 119 List<DecodedFletchSelector> selectors = methodTable.keys.toList()..sort(); | |
| 120 for (DecodedFletchSelector selector in selectors) { | |
| 121 int methodId = methodTable[selector]; | |
| 122 unseen.remove(system.lookupFunctionById(methodId)); | |
| 123 writeMethodTableEntry(selector, methodId); | |
| 124 } | |
| 125 }); | |
| 126 writeLine("}"); | |
| 127 } | |
| 128 | |
| 129 String generateDebugString() { | |
| 130 buffer.clear(); | |
| 131 | |
| 132 Map<String, List<Element>> elementsByPath = <String, List<Element>>{}; | |
| 133 Set<FletchFunction> unseenFunctions = new Set<FletchFunction>(); | |
| 134 | |
| 135 for (var pair in system.functionsById) { | |
| 136 unseenFunctions.add(pair.snd); | |
| 137 } | |
| 138 | |
| 139 groupByPath(pair) { | |
| 140 Element element = pair.fst; | |
| 141 String path = | |
| 142 relativize(base, element.compilationUnit.script.resourceUri, false); | |
| 143 List<Element> elements = | |
| 144 elementsByPath.putIfAbsent(path, () => <Element>[]); | |
| 145 elements.add(element); | |
| 146 } | |
| 147 system.functionsByElement.forEach(groupByPath); | |
| 148 system.classesByElement.forEach(groupByPath); | |
| 149 List paths = elementsByPath.keys.toList(); | |
| 150 paths.sort(); | |
| 151 for (String path in paths) { | |
| 152 writeLine("$path"); | |
| 153 indented(() { | |
| 154 List<Element> elements = elementsByPath[path]; | |
| 155 elements.sort((a, b) => "$a".compareTo("$b")); | |
| 156 for (Element element in elements) { | |
| 157 if (element.isClass) { | |
| 158 writeFletchClass(system.classesByElement[element], unseenFunctions); | |
| 159 } else if (!element.isInstanceMember) { | |
| 160 unseenFunctions.remove(system.functionsByElement[element]); | |
| 161 // TODO(ahe): It would probably be better to call | |
| 162 // writeFletchFunctionAsBody here, but we have an element, not an | |
| 163 // ID. | |
| 164 writeLine("$element"); | |
| 165 } | |
| 166 } | |
| 167 }); | |
| 168 } | |
| 169 | |
| 170 writeLine("Classes without an element:"); | |
| 171 indented(() { | |
| 172 for (var pair in system.classesById) { | |
| 173 FletchClass fletchClass = pair.snd; | |
| 174 if (system.classesByElement[fletchClass.element] != fletchClass) { | |
| 175 writeFletchClass(fletchClass, unseenFunctions); | |
| 176 } | |
| 177 } | |
| 178 }); | |
| 179 | |
| 180 writeLine("Other functions:"); | |
| 181 indented(() { | |
| 182 for (var pair in system.functionsById) { | |
| 183 FletchFunction fletchFunction = pair.snd; | |
| 184 if (unseenFunctions.remove(fletchFunction)) { | |
| 185 write("$fletchFunction "); | |
| 186 writeFletchFunctionAsBody(fletchFunction); | |
| 187 } | |
| 188 } | |
| 189 }); | |
| 190 | |
| 191 return "$buffer"; | |
| 192 } | |
| 193 | |
| 194 int compareUnits(CompilationUnitElement a, CompilationUnitElement b) { | |
| 195 String aPath = relativize(base, a.script.resourceUri, false); | |
| 196 String bPath = relativize(base, b.script.resourceUri, false); | |
| 197 return aPath.compareTo(bPath); | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 class DecodedFletchSelector implements Comparable<DecodedFletchSelector> { | |
| 202 final FletchSelector selector; | |
| 203 | |
| 204 final String symbol; | |
| 205 | |
| 206 const DecodedFletchSelector(this.selector, this.symbol); | |
| 207 | |
| 208 factory DecodedFletchSelector.fromEncodedSelector( | |
| 209 int encodedSelector, | |
| 210 FletchSystem system) { | |
| 211 FletchSelector selector = new FletchSelector(encodedSelector); | |
| 212 return new DecodedFletchSelector( | |
| 213 selector, system.symbolByFletchSelectorId[selector.id]); | |
| 214 } | |
| 215 | |
| 216 int get id => selector.id; | |
| 217 | |
| 218 SelectorKind get kind => selector.kind; | |
| 219 | |
| 220 int get arity => selector.arity; | |
| 221 | |
| 222 String toString() => "DecodedFletchSelector($id, $symbol, $kind, $arity)"; | |
| 223 | |
| 224 int compareTo(DecodedFletchSelector other) { | |
| 225 int result = this.symbol.compareTo(other.symbol); | |
| 226 if (result != 0) return result; | |
| 227 result = this.kind.index.compareTo(other.kind.index); | |
| 228 if (result != 0) return result; | |
| 229 return this.arity.compareTo(other.arity); | |
| 230 } | |
| 231 } | |
| OLD | NEW |