OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.compiler_base; | 5 library dart2js.compiler_base; |
6 | 6 |
7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
8 | 8 |
9 import '../compiler_new.dart' as api; | 9 import '../compiler_new.dart' as api; |
10 import 'backend_strategy.dart'; | 10 import 'backend_strategy.dart'; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 | 119 |
120 DiagnosticReporter get reporter => _reporter; | 120 DiagnosticReporter get reporter => _reporter; |
121 ElementEnvironment get elementEnvironment => _elementEnvironment; | 121 ElementEnvironment get elementEnvironment => _elementEnvironment; |
122 CommonElements get commonElements => _commonElements; | 122 CommonElements get commonElements => _commonElements; |
123 Resolution get resolution => _resolution; | 123 Resolution get resolution => _resolution; |
124 ParsingContext get parsingContext => _parsingContext; | 124 ParsingContext get parsingContext => _parsingContext; |
125 | 125 |
126 // TODO(zarah): Remove this map and incorporate compile-time errors | 126 // TODO(zarah): Remove this map and incorporate compile-time errors |
127 // in the model. | 127 // in the model. |
128 /// Tracks elements with compile-time errors. | 128 /// Tracks elements with compile-time errors. |
129 final Map<Element, List<DiagnosticMessage>> elementsWithCompileTimeErrors = | 129 final Map<Entity, List<DiagnosticMessage>> elementsWithCompileTimeErrors = |
130 new Map<Element, List<DiagnosticMessage>>(); | 130 new Map<Entity, List<DiagnosticMessage>>(); |
131 | 131 |
132 final Environment environment; | 132 final Environment environment; |
133 // TODO(sigmund): delete once we migrate the rest of the compiler to use | 133 // TODO(sigmund): delete once we migrate the rest of the compiler to use |
134 // `environment` directly. | 134 // `environment` directly. |
135 @deprecated | 135 @deprecated |
136 fromEnvironment(String name) => environment.valueOf(name); | 136 fromEnvironment(String name) => environment.valueOf(name); |
137 | 137 |
138 Element get currentElement => _reporter.currentElement; | 138 Entity get currentElement => _reporter.currentElement; |
139 | 139 |
140 List<CompilerTask> tasks; | 140 List<CompilerTask> tasks; |
141 ScannerTask scanner; | 141 ScannerTask scanner; |
142 DietParserTask dietParser; | 142 DietParserTask dietParser; |
143 ParserTask parser; | 143 ParserTask parser; |
144 PatchParserTask patchParser; | 144 PatchParserTask patchParser; |
145 LibraryLoaderTask libraryLoader; | 145 LibraryLoaderTask libraryLoader; |
146 SerializationTask serialization; | 146 SerializationTask serialization; |
147 ResolverTask resolver; | 147 ResolverTask resolver; |
148 closureMapping.ClosureTask closureToClassMapper; | 148 closureMapping.ClosureTask closureToClassMapper; |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 return resolutionEnqueuer; | 512 return resolutionEnqueuer; |
513 } | 513 } |
514 | 514 |
515 /// Performs the compilation when all libraries have been loaded. | 515 /// Performs the compilation when all libraries have been loaded. |
516 void compileLoadedLibraries(LibraryEntity rootLibrary) => | 516 void compileLoadedLibraries(LibraryEntity rootLibrary) => |
517 selfTask.measureSubtask("Compiler.compileLoadedLibraries", () { | 517 selfTask.measureSubtask("Compiler.compileLoadedLibraries", () { |
518 ResolutionEnqueuer resolutionEnqueuer = startResolution(); | 518 ResolutionEnqueuer resolutionEnqueuer = startResolution(); |
519 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl(); | 519 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl(); |
520 mainFunction = frontEndStrategy.computeMain(rootLibrary, mainImpact); | 520 mainFunction = frontEndStrategy.computeMain(rootLibrary, mainImpact); |
521 | 521 |
522 mirrorUsageAnalyzerTask.analyzeUsage(rootLibrary); | 522 if (!options.loadFromDill) { |
| 523 // TODO(johnniwinther): Support mirrors usages analysis from dill. |
| 524 mirrorUsageAnalyzerTask.analyzeUsage(rootLibrary); |
| 525 } |
523 | 526 |
524 // In order to see if a library is deferred, we must compute the | 527 // In order to see if a library is deferred, we must compute the |
525 // compile-time constants that are metadata. This means adding | 528 // compile-time constants that are metadata. This means adding |
526 // something to the resolution queue. So we cannot wait with | 529 // something to the resolution queue. So we cannot wait with |
527 // this until after the resolution queue is processed. | 530 // this until after the resolution queue is processed. |
528 deferredLoadTask.beforeResolution(this); | 531 deferredLoadTask.beforeResolution(this); |
529 impactStrategy = backend.createImpactStrategy( | 532 impactStrategy = backend.createImpactStrategy( |
530 supportDeferredLoad: deferredLoadTask.isProgramSplit, | 533 supportDeferredLoad: deferredLoadTask.isProgramSplit, |
531 supportDumpInfo: options.dumpInfo, | 534 supportDumpInfo: options.dumpInfo, |
532 supportSerialization: serialization.supportSerialization); | 535 supportSerialization: serialization.supportSerialization); |
(...skipping 17 matching lines...) Expand all Loading... |
550 resolutionEnqueuer | 553 resolutionEnqueuer |
551 .applyImpact(computeImpactForLibrary(rootLibrary)); | 554 .applyImpact(computeImpactForLibrary(rootLibrary)); |
552 } | 555 } |
553 if (librariesToAnalyzeWhenRun != null) { | 556 if (librariesToAnalyzeWhenRun != null) { |
554 for (Uri libraryUri in librariesToAnalyzeWhenRun) { | 557 for (Uri libraryUri in librariesToAnalyzeWhenRun) { |
555 resolutionEnqueuer.applyImpact(computeImpactForLibrary( | 558 resolutionEnqueuer.applyImpact(computeImpactForLibrary( |
556 libraryLoader.lookupLibrary(libraryUri))); | 559 libraryLoader.lookupLibrary(libraryUri))); |
557 } | 560 } |
558 } | 561 } |
559 } | 562 } |
560 if (commonElements.mirrorsLibrary != null) { | 563 if (commonElements.mirrorsLibrary != null && !options.loadFromDill) { |
| 564 // TODO(johnniwinther): Support mirrors from dill. |
561 resolveLibraryMetadata(); | 565 resolveLibraryMetadata(); |
562 } | 566 } |
563 reporter.log('Resolving...'); | 567 reporter.log('Resolving...'); |
564 | 568 |
565 processQueue(resolutionEnqueuer, mainFunction, libraryLoader.libraries, | 569 processQueue(resolutionEnqueuer, mainFunction, libraryLoader.libraries, |
566 onProgress: showResolutionProgress); | 570 onProgress: showResolutionProgress); |
567 backend.onResolutionEnd(); | 571 backend.onResolutionEnd(); |
568 resolutionEnqueuer.logSummary(reporter.log); | 572 resolutionEnqueuer.logSummary(reporter.log); |
569 | 573 |
570 _reporter.reportSuppressedMessagesSummary(); | 574 _reporter.reportSuppressedMessagesSummary(); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 int slashPos = libraryUri.path.indexOf('/'); | 928 int slashPos = libraryUri.path.indexOf('/'); |
925 if (slashPos != -1) { | 929 if (slashPos != -1) { |
926 String packageName = libraryUri.path.substring(0, slashPos); | 930 String packageName = libraryUri.path.substring(0, slashPos); |
927 return new Uri(scheme: 'package', path: packageName); | 931 return new Uri(scheme: 'package', path: packageName); |
928 } | 932 } |
929 } | 933 } |
930 return libraryUri; | 934 return libraryUri; |
931 } | 935 } |
932 | 936 |
933 /// Returns [true] if a compile-time error has been reported for element. | 937 /// Returns [true] if a compile-time error has been reported for element. |
934 bool elementHasCompileTimeError(Element element) { | 938 bool elementHasCompileTimeError(Entity element) { |
935 return elementsWithCompileTimeErrors.containsKey(element); | 939 return elementsWithCompileTimeErrors.containsKey(element); |
936 } | 940 } |
937 | 941 |
938 /// Associate [element] with a compile-time error [message]. | 942 /// Associate [element] with a compile-time error [message]. |
939 void registerCompileTimeError(Element element, DiagnosticMessage message) { | 943 void registerCompileTimeError(Entity element, DiagnosticMessage message) { |
940 // The information is only needed if [generateCodeWithCompileTimeErrors]. | 944 // The information is only needed if [generateCodeWithCompileTimeErrors]. |
941 if (options.generateCodeWithCompileTimeErrors) { | 945 if (options.generateCodeWithCompileTimeErrors) { |
942 if (element == null) { | 946 if (element == null) { |
943 // Record as global error. | 947 // Record as global error. |
944 // TODO(zarah): Extend element model to represent compile-time | 948 // TODO(zarah): Extend element model to represent compile-time |
945 // errors instead of using a map. | 949 // errors instead of using a map. |
946 element = mainFunction as MethodElement; | 950 element = mainFunction; |
947 } | 951 } |
948 elementsWithCompileTimeErrors | 952 elementsWithCompileTimeErrors |
949 .putIfAbsent(element, () => <DiagnosticMessage>[]) | 953 .putIfAbsent(element, () => <DiagnosticMessage>[]) |
950 .add(message); | 954 .add(message); |
951 } | 955 } |
952 } | 956 } |
953 | 957 |
954 api.OutputSink outputProvider( | 958 api.OutputSink outputProvider( |
955 String name, String extension, api.OutputType type) { | 959 String name, String extension, api.OutputType type) { |
956 if (compilationFailed) { | 960 if (compilationFailed) { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 lastDiagnosticWasFiltered = false; | 1059 lastDiagnosticWasFiltered = false; |
1056 reportDiagnostic(message, infos, kind); | 1060 reportDiagnostic(message, infos, kind); |
1057 } | 1061 } |
1058 | 1062 |
1059 void reportDiagnostic(DiagnosticMessage message, | 1063 void reportDiagnostic(DiagnosticMessage message, |
1060 List<DiagnosticMessage> infos, api.Diagnostic kind) { | 1064 List<DiagnosticMessage> infos, api.Diagnostic kind) { |
1061 compiler.reportDiagnostic(message, infos, kind); | 1065 compiler.reportDiagnostic(message, infos, kind); |
1062 if (kind == api.Diagnostic.ERROR || | 1066 if (kind == api.Diagnostic.ERROR || |
1063 kind == api.Diagnostic.CRASH || | 1067 kind == api.Diagnostic.CRASH || |
1064 (options.fatalWarnings && kind == api.Diagnostic.WARNING)) { | 1068 (options.fatalWarnings && kind == api.Diagnostic.WARNING)) { |
1065 Element errorElement; | 1069 Entity errorElement; |
1066 if (message.spannable is Element) { | 1070 if (message.spannable is Entity) { |
1067 errorElement = message.spannable; | 1071 errorElement = message.spannable; |
1068 } else { | 1072 } else { |
1069 errorElement = currentElement; | 1073 errorElement = currentElement; |
1070 } | 1074 } |
1071 compiler.registerCompileTimeError(errorElement, message); | 1075 compiler.registerCompileTimeError(errorElement, message); |
1072 compiler.fatalDiagnosticReported(message, infos, kind); | 1076 compiler.fatalDiagnosticReported(message, infos, kind); |
1073 } | 1077 } |
1074 } | 1078 } |
1075 | 1079 |
1076 @override | 1080 @override |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 | 1116 |
1113 void reportAssertionFailure(SpannableAssertionFailure ex) { | 1117 void reportAssertionFailure(SpannableAssertionFailure ex) { |
1114 String message = | 1118 String message = |
1115 (ex.message != null) ? tryToString(ex.message) : tryToString(ex); | 1119 (ex.message != null) ? tryToString(ex.message) : tryToString(ex); |
1116 reportDiagnosticInternal( | 1120 reportDiagnosticInternal( |
1117 createMessage(ex.node, MessageKind.GENERIC, {'text': message}), | 1121 createMessage(ex.node, MessageKind.GENERIC, {'text': message}), |
1118 const <DiagnosticMessage>[], | 1122 const <DiagnosticMessage>[], |
1119 api.Diagnostic.CRASH); | 1123 api.Diagnostic.CRASH); |
1120 } | 1124 } |
1121 | 1125 |
1122 @override | 1126 /// Using [frontEndStrategy] to compute a [SourceSpan] from spannable using |
1123 SourceSpan spanFromToken(Token token) => spanFromTokens(token, token); | 1127 /// the [currentElement] as context. |
1124 | 1128 SourceSpan _spanFromStrategy(Spannable spannable) { |
1125 SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { | 1129 SourceSpan span = |
1126 if (begin == null || end == null) { | 1130 compiler.frontEndStrategy.spanFromSpannable(spannable, currentElement); |
1127 // TODO(ahe): We can almost always do better. Often it is only | 1131 if (span != null) return span; |
1128 // end that is null. Otherwise, we probably know the current | 1132 throw 'No error location.'; |
1129 // URI. | |
1130 throw 'Cannot find tokens to produce error message.'; | |
1131 } | |
1132 if (uri == null && currentElement != null) { | |
1133 if (currentElement is! Element) { | |
1134 throw 'Can only find tokens from an Element.'; | |
1135 } | |
1136 Element element = currentElement; | |
1137 uri = element.compilationUnit.script.resourceUri; | |
1138 assert(invariant(currentElement, () { | |
1139 bool sameToken(Token token, Token sought) { | |
1140 if (token == sought) return true; | |
1141 if (token.stringValue == '>>') { | |
1142 // `>>` is converted to `>` in the parser when needed. | |
1143 return sought.stringValue == '>' && | |
1144 token.charOffset <= sought.charOffset && | |
1145 sought.charOffset < token.charEnd; | |
1146 } | |
1147 return false; | |
1148 } | |
1149 | |
1150 /// Check that [begin] and [end] can be found between [from] and [to]. | |
1151 validateToken(Token from, Token to) { | |
1152 if (from == null || to == null) return true; | |
1153 bool foundBegin = false; | |
1154 bool foundEnd = false; | |
1155 Token token = from; | |
1156 while (true) { | |
1157 if (sameToken(token, begin)) { | |
1158 foundBegin = true; | |
1159 } | |
1160 if (sameToken(token, end)) { | |
1161 foundEnd = true; | |
1162 } | |
1163 if (foundBegin && foundEnd) { | |
1164 return true; | |
1165 } | |
1166 if (token == to || token == token.next || token.next == null) { | |
1167 break; | |
1168 } | |
1169 token = token.next; | |
1170 } | |
1171 | |
1172 // Create a good message for when the tokens were not found. | |
1173 StringBuffer sb = new StringBuffer(); | |
1174 sb.write('Invalid current element: $element. '); | |
1175 sb.write('Looking for '); | |
1176 sb.write('[${begin} (${begin.hashCode}),'); | |
1177 sb.write('${end} (${end.hashCode})] in'); | |
1178 | |
1179 token = from; | |
1180 while (true) { | |
1181 sb.write('\n ${token} (${token.hashCode})'); | |
1182 if (token == to || token == token.next || token.next == null) { | |
1183 break; | |
1184 } | |
1185 token = token.next; | |
1186 } | |
1187 return sb.toString(); | |
1188 } | |
1189 | |
1190 if (element.enclosingClass != null && | |
1191 element.enclosingClass.isEnumClass) { | |
1192 // Enums ASTs are synthesized (and give messed up messages). | |
1193 return true; | |
1194 } | |
1195 | |
1196 if (element is AstElement) { | |
1197 AstElement astElement = element; | |
1198 if (astElement.hasNode) { | |
1199 Token from = astElement.node.getBeginToken(); | |
1200 Token to = astElement.node.getEndToken(); | |
1201 if (astElement.metadata.isNotEmpty) { | |
1202 if (!astElement.metadata.first.hasNode) { | |
1203 // We might try to report an error while parsing the metadata | |
1204 // itself. | |
1205 return true; | |
1206 } | |
1207 from = astElement.metadata.first.node.getBeginToken(); | |
1208 } | |
1209 return validateToken(from, to); | |
1210 } | |
1211 } | |
1212 return true; | |
1213 }, message: "Invalid current element: $element [$begin,$end].")); | |
1214 } | |
1215 return new SourceSpan.fromTokens(uri, begin, end); | |
1216 } | 1133 } |
1217 | 1134 |
1218 SourceSpan spanFromNode(Node node) { | 1135 SourceSpan spanFromSpannable(Spannable spannable) { |
1219 return spanFromTokens(node.getBeginToken(), node.getPrefixEndToken()); | 1136 if (spannable == CURRENT_ELEMENT_SPANNABLE) { |
1220 } | 1137 spannable = currentElement; |
1221 | 1138 } else if (spannable == NO_LOCATION_SPANNABLE) { |
1222 SourceSpan spanFromElement(Element element) { | 1139 if (currentElement == null) return null; |
1223 if (element != null && element.sourcePosition != null) { | 1140 spannable = currentElement; |
1224 return element.sourcePosition; | |
1225 } | 1141 } |
1226 while (element != null && element.isSynthesized) { | 1142 if (spannable is SourceSpan) { |
1227 element = element.enclosingElement; | 1143 return spannable; |
1228 } | 1144 } else if (spannable is HInstruction) { |
1229 if (element != null && | 1145 Entity element = spannable.sourceElement; |
1230 element.sourcePosition == null && | 1146 if (element == null) element = currentElement; |
1231 !element.isLibrary && | 1147 SourceInformation position = spannable.sourceInformation; |
1232 !element.isCompilationUnit) { | 1148 if (position != null) return position.sourceSpan; |
1233 // Sometimes, the backend fakes up elements that have no | 1149 return _spanFromStrategy(element); |
1234 // position. So we use the enclosing element instead. It is | 1150 } else if (spannable is Local) { |
1235 // not a good error location, but cancel really is "internal | 1151 Local local = spannable; |
1236 // error" or "not implemented yet", so the vicinity is good | 1152 return _spanFromStrategy(local.executableContext); |
1237 // enough for now. | |
1238 element = element.enclosingElement; | |
1239 // TODO(ahe): I plan to overhaul this infrastructure anyways. | |
1240 } | |
1241 if (element == null) { | |
1242 element = currentElement; | |
1243 } | |
1244 if (element == null) { | |
1245 return null; | |
1246 } | |
1247 | |
1248 if (element.sourcePosition != null) { | |
1249 return element.sourcePosition; | |
1250 } | |
1251 Token position = element.position; | |
1252 Uri uri = element.compilationUnit.script.resourceUri; | |
1253 return (position == null) | |
1254 ? new SourceSpan(uri, 0, 0) | |
1255 : spanFromTokens(position, position, uri); | |
1256 } | |
1257 | |
1258 SourceSpan spanFromHInstruction(HInstruction instruction) { | |
1259 Element element = _elementFromHInstruction(instruction); | |
1260 if (element == null) element = currentElement; | |
1261 SourceInformation position = instruction.sourceInformation; | |
1262 if (position == null) return spanFromElement(element); | |
1263 return position.sourceSpan; | |
1264 } | |
1265 | |
1266 SourceSpan spanFromSpannable(Spannable node) { | |
1267 if (node == CURRENT_ELEMENT_SPANNABLE) { | |
1268 node = currentElement; | |
1269 } else if (node == NO_LOCATION_SPANNABLE) { | |
1270 if (currentElement == null) return null; | |
1271 node = currentElement; | |
1272 } | |
1273 if (node is SourceSpan) { | |
1274 return node; | |
1275 } else if (node is Node) { | |
1276 return spanFromNode(node); | |
1277 } else if (node is HInstruction) { | |
1278 return spanFromHInstruction(node); | |
1279 } else if (node is Element) { | |
1280 return spanFromElement(node); | |
1281 } else if (node is MetadataAnnotation) { | |
1282 return node.sourcePosition; | |
1283 } else if (node is Local) { | |
1284 Local local = node; | |
1285 return spanFromElement(local.executableContext); | |
1286 } else if (node is Entity) { | |
1287 return spanFromElement(currentElement); | |
1288 } else { | 1153 } else { |
1289 throw 'No error location.'; | 1154 return _spanFromStrategy(spannable); |
1290 } | 1155 } |
1291 } | 1156 } |
1292 | 1157 |
| 1158 // TODO(johnniwinther): Move this to the parser listeners. |
| 1159 @override |
| 1160 SourceSpan spanFromToken(Token token) { |
| 1161 if (compiler.frontEndStrategy is ResolutionFrontEndStrategy) { |
| 1162 ResolutionFrontEndStrategy strategy = compiler.frontEndStrategy; |
| 1163 return strategy.spanFromToken(currentElement, token); |
| 1164 } |
| 1165 throw 'No error location.'; |
| 1166 } |
| 1167 |
1293 Element _elementFromHInstruction(HInstruction instruction) { | 1168 Element _elementFromHInstruction(HInstruction instruction) { |
1294 return instruction.sourceElement is Element | 1169 return instruction.sourceElement is Element |
1295 ? instruction.sourceElement | 1170 ? instruction.sourceElement |
1296 : null; | 1171 : null; |
1297 } | 1172 } |
1298 | 1173 |
1299 internalError(Spannable node, reason) { | 1174 internalError(Spannable spannable, reason) { |
1300 String message = tryToString(reason); | 1175 String message = tryToString(reason); |
1301 reportDiagnosticInternal( | 1176 reportDiagnosticInternal( |
1302 createMessage(node, MessageKind.GENERIC, {'text': message}), | 1177 createMessage(spannable, MessageKind.GENERIC, {'text': message}), |
1303 const <DiagnosticMessage>[], | 1178 const <DiagnosticMessage>[], |
1304 api.Diagnostic.CRASH); | 1179 api.Diagnostic.CRASH); |
1305 throw 'Internal Error: $message'; | 1180 throw 'Internal Error: $message'; |
1306 } | 1181 } |
1307 | 1182 |
1308 void unhandledExceptionOnElement(Entity element) { | 1183 void unhandledExceptionOnElement(Entity element) { |
1309 if (hasCrashed) return; | 1184 if (hasCrashed) return; |
1310 hasCrashed = true; | 1185 hasCrashed = true; |
1311 reportDiagnostic(createMessage(element, MessageKind.COMPILER_CRASHED), | 1186 reportDiagnostic(createMessage(element, MessageKind.COMPILER_CRASHED), |
1312 const <DiagnosticMessage>[], api.Diagnostic.CRASH); | 1187 const <DiagnosticMessage>[], api.Diagnostic.CRASH); |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1685 _ElementScanner(this.scanner); | 1560 _ElementScanner(this.scanner); |
1686 void scanLibrary(LibraryElement library) => scanner.scanLibrary(library); | 1561 void scanLibrary(LibraryElement library) => scanner.scanLibrary(library); |
1687 void scanUnit(CompilationUnitElement unit) => scanner.scan(unit); | 1562 void scanUnit(CompilationUnitElement unit) => scanner.scan(unit); |
1688 } | 1563 } |
1689 | 1564 |
1690 class _EmptyEnvironment implements Environment { | 1565 class _EmptyEnvironment implements Environment { |
1691 const _EmptyEnvironment(); | 1566 const _EmptyEnvironment(); |
1692 | 1567 |
1693 String valueOf(String key) => null; | 1568 String valueOf(String key) => null; |
1694 } | 1569 } |
OLD | NEW |