| 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_compiler_implementation; | |
| 6 | |
| 7 import 'dart:async' show | |
| 8 EventSink; | |
| 9 | |
| 10 import 'package:compiler/compiler_new.dart' as api; | |
| 11 | |
| 12 import 'package:compiler/src/apiimpl.dart' show | |
| 13 CompilerImpl, | |
| 14 makeDiagnosticOptions; | |
| 15 | |
| 16 import 'package:compiler/src/io/source_file.dart'; | |
| 17 | |
| 18 import 'package:compiler/src/source_file_provider.dart' show | |
| 19 SourceFileProvider; | |
| 20 | |
| 21 import 'package:compiler/src/elements/modelx.dart' show | |
| 22 CompilationUnitElementX, | |
| 23 LibraryElementX; | |
| 24 | |
| 25 import 'package:compiler/compiler_new.dart' show | |
| 26 CompilerOutput; | |
| 27 | |
| 28 import 'package:compiler/src/diagnostics/messages.dart' show | |
| 29 Message, | |
| 30 MessageKind, | |
| 31 MessageTemplate; | |
| 32 | |
| 33 import 'package:compiler/src/diagnostics/source_span.dart' show | |
| 34 SourceSpan; | |
| 35 | |
| 36 import 'package:compiler/src/diagnostics/diagnostic_listener.dart' show | |
| 37 DiagnosticMessage, | |
| 38 DiagnosticReporter; | |
| 39 | |
| 40 import 'package:compiler/src/diagnostics/spannable.dart' show | |
| 41 Spannable; | |
| 42 | |
| 43 import 'fletch_function_builder.dart'; | |
| 44 import 'debug_info.dart'; | |
| 45 import 'find_position_visitor.dart'; | |
| 46 import 'fletch_context.dart'; | |
| 47 | |
| 48 import 'fletch_enqueuer.dart' show | |
| 49 FletchEnqueueTask; | |
| 50 | |
| 51 import '../fletch_system.dart'; | |
| 52 import 'package:compiler/src/diagnostics/diagnostic_listener.dart'; | |
| 53 import 'package:compiler/src/elements/elements.dart'; | |
| 54 | |
| 55 import '../incremental/fletchc_incremental.dart' show | |
| 56 IncrementalCompiler; | |
| 57 | |
| 58 import 'fletch_diagnostic_reporter.dart' show | |
| 59 FletchDiagnosticReporter; | |
| 60 | |
| 61 const EXTRA_DART2JS_OPTIONS = const <String>[ | |
| 62 // TODO(ahe): This doesn't completely disable type inference. Investigate. | |
| 63 '--disable-type-inference', | |
| 64 '--output-type=dart', | |
| 65 // We want to continue generating code in the case of errors, to support | |
| 66 // incremental fixes of erroneous code. | |
| 67 '--generate-code-with-compile-time-errors', | |
| 68 ]; | |
| 69 | |
| 70 const FLETCH_PATCHES = const <String, String>{ | |
| 71 "_internal": "internal/internal_patch.dart", | |
| 72 "collection": "collection/collection_patch.dart", | |
| 73 "convert": "convert/convert_patch.dart", | |
| 74 "math": "math/math_patch.dart", | |
| 75 "async": "async/async_patch.dart", | |
| 76 "typed_data": "typed_data/typed_data_patch.dart", | |
| 77 }; | |
| 78 | |
| 79 const FLETCH_PLATFORM = 3; | |
| 80 | |
| 81 DiagnosticOptions makeFletchDiagnosticOptions( | |
| 82 {bool suppressWarnings: false, | |
| 83 bool fatalWarnings: false, | |
| 84 bool suppressHints: false, | |
| 85 bool terseDiagnostics: false, | |
| 86 bool showPackageWarnings: true}) { | |
| 87 return makeDiagnosticOptions( | |
| 88 suppressWarnings: suppressWarnings, | |
| 89 fatalWarnings: fatalWarnings, | |
| 90 suppressHints: suppressHints, | |
| 91 terseDiagnostics: terseDiagnostics, | |
| 92 showPackageWarnings: true); | |
| 93 } | |
| 94 | |
| 95 class FletchCompilerImplementation extends CompilerImpl { | |
| 96 final Uri fletchVm; | |
| 97 | |
| 98 final Uri nativesJson; | |
| 99 | |
| 100 final IncrementalCompiler incrementalCompiler; | |
| 101 | |
| 102 Map<Uri, CompilationUnitElementX> compilationUnits; | |
| 103 FletchContext internalContext; | |
| 104 | |
| 105 /// A reference to [../compiler.dart:FletchCompiler] used for testing. | |
| 106 // TODO(ahe): Clean this up and remove this. | |
| 107 var helper; | |
| 108 | |
| 109 @override | |
| 110 FletchEnqueueTask get enqueuer => super.enqueuer; | |
| 111 | |
| 112 FletchCompilerImplementation( | |
| 113 api.CompilerInput provider, | |
| 114 api.CompilerOutput outputProvider, | |
| 115 api.CompilerDiagnostics handler, | |
| 116 Uri libraryRoot, | |
| 117 Uri packageConfig, | |
| 118 this.nativesJson, | |
| 119 List<String> options, | |
| 120 Map<String, dynamic> environment, | |
| 121 this.fletchVm, | |
| 122 this.incrementalCompiler) | |
| 123 : super( | |
| 124 provider, outputProvider, handler, libraryRoot, null, | |
| 125 EXTRA_DART2JS_OPTIONS.toList()..addAll(options), environment, | |
| 126 packageConfig, null, FletchBackend.createInstance, | |
| 127 FletchDiagnosticReporter.createInstance, | |
| 128 makeFletchDiagnosticOptions); | |
| 129 | |
| 130 FletchContext get context { | |
| 131 if (internalContext == null) { | |
| 132 internalContext = new FletchContext(this); | |
| 133 } | |
| 134 return internalContext; | |
| 135 } | |
| 136 | |
| 137 String fletchPatchLibraryFor(String name) { | |
| 138 // TODO(sigurdm): Try to remove this special casing. | |
| 139 if (name == "core") { | |
| 140 return platformConfigUri.path.endsWith("fletch_embedded.platform") | |
| 141 ? "core/embedded_core_patch.dart" | |
| 142 : "core/core_patch.dart"; | |
| 143 } | |
| 144 return FLETCH_PATCHES[name]; | |
| 145 } | |
| 146 | |
| 147 @override | |
| 148 Uri resolvePatchUri(String dartLibraryPath) { | |
| 149 String path = fletchPatchLibraryFor(dartLibraryPath); | |
| 150 if (path == null) return null; | |
| 151 // Fletch patches are located relative to [libraryRoot]. | |
| 152 return libraryRoot.resolve(path); | |
| 153 } | |
| 154 | |
| 155 CompilationUnitElementX compilationUnitForUri(Uri uri) { | |
| 156 if (compilationUnits == null) { | |
| 157 compilationUnits = <Uri, CompilationUnitElementX>{}; | |
| 158 libraryLoader.libraries.forEach((LibraryElementX library) { | |
| 159 for (CompilationUnitElementX unit in library.compilationUnits) { | |
| 160 compilationUnits[unit.script.resourceUri] = unit; | |
| 161 } | |
| 162 }); | |
| 163 } | |
| 164 return compilationUnits[uri]; | |
| 165 } | |
| 166 | |
| 167 DebugInfo debugInfoForPosition( | |
| 168 Uri file, | |
| 169 int position, | |
| 170 FletchSystem currentSystem) { | |
| 171 Uri uri = Uri.base.resolveUri(file); | |
| 172 CompilationUnitElementX unit = compilationUnitForUri(uri); | |
| 173 if (unit == null) return null; | |
| 174 FindPositionVisitor visitor = new FindPositionVisitor(position, unit); | |
| 175 unit.accept(visitor, null); | |
| 176 FletchFunctionBuilder builder = | |
| 177 context.backend.systemBuilder.lookupFunctionBuilderByElement( | |
| 178 visitor.element); | |
| 179 if (builder == null) return null; | |
| 180 // TODO(ajohnsen): We need a mapping from element to functionId, that can | |
| 181 // be looked up in the current fletch system. | |
| 182 FletchFunction function = builder.finalizeFunction(context, []); | |
| 183 return context.backend.createDebugInfo(function, currentSystem); | |
| 184 } | |
| 185 | |
| 186 int positionInFileFromPattern(Uri file, int line, String pattern) { | |
| 187 Uri uri = Uri.base.resolveUri(file); | |
| 188 SourceFile sourceFile = getSourceFile(provider, uri); | |
| 189 if (sourceFile == null) return null; | |
| 190 List<int> lineStarts = sourceFile.lineStarts; | |
| 191 if (line >= lineStarts.length) return null; | |
| 192 int begin = lineStarts[line]; | |
| 193 int end = line + 2 < lineStarts.length | |
| 194 ? lineStarts[line + 1] | |
| 195 : sourceFile.length; | |
| 196 String lineText = sourceFile.slowSubstring(begin, end); | |
| 197 int column = lineText.indexOf(pattern); | |
| 198 if (column == -1) return null; | |
| 199 return begin + column; | |
| 200 } | |
| 201 | |
| 202 int positionInFile(Uri file, int line, int column) { | |
| 203 Uri uri = Uri.base.resolveUri(file); | |
| 204 SourceFile sourceFile = getSourceFile(provider, uri); | |
| 205 if (sourceFile == null) return null; | |
| 206 if (line >= sourceFile.lineStarts.length) return null; | |
| 207 return sourceFile.lineStarts[line] + column; | |
| 208 } | |
| 209 | |
| 210 Iterable<Uri> findSourceFiles(Pattern pattern) { | |
| 211 SourceFileProvider provider = this.provider; | |
| 212 return provider.sourceFiles.keys.where((Uri uri) { | |
| 213 return pattern.matchAsPrefix(uri.pathSegments.last) != null; | |
| 214 }); | |
| 215 } | |
| 216 | |
| 217 void reportVerboseInfo( | |
| 218 Spannable node, | |
| 219 String messageText, | |
| 220 {bool forceVerbose: false}) { | |
| 221 // TODO(johnniwinther): Use super.reportVerboseInfo once added. | |
| 222 if (forceVerbose || verbose) { | |
| 223 MessageTemplate template = MessageTemplate.TEMPLATES[MessageKind.GENERIC]; | |
| 224 SourceSpan span = reporter.spanFromSpannable(node); | |
| 225 Message message = template.message({'text': messageText}); | |
| 226 reportDiagnostic(new DiagnosticMessage(span, node, message), | |
| 227 [], api.Diagnostic.HINT); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 @override | |
| 232 void compileLoadedLibraries() { | |
| 233 // TODO(ahe): Ensure fletchSystemLibrary is not null | |
| 234 // (also when mainApp is null). | |
| 235 if (mainApp == null) { | |
| 236 return; | |
| 237 } | |
| 238 super.compileLoadedLibraries(); | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 /// Output provider which collects output in [output]. | |
| 243 class OutputProvider implements CompilerOutput { | |
| 244 final Map<String, String> output = new Map<String, String>(); | |
| 245 | |
| 246 EventSink<String> createEventSink(String name, String extension) { | |
| 247 return new StringEventSink((String data) { | |
| 248 output['$name.$extension'] = data; | |
| 249 }); | |
| 250 } | |
| 251 | |
| 252 String operator[](String key) => output[key]; | |
| 253 } | |
| 254 | |
| 255 /// Helper class to collect sources. | |
| 256 class StringEventSink implements EventSink<String> { | |
| 257 List<String> data = <String>[]; | |
| 258 | |
| 259 final Function onClose; | |
| 260 | |
| 261 StringEventSink(this.onClose); | |
| 262 | |
| 263 void add(String event) { | |
| 264 if (data == null) throw 'StringEventSink is closed.'; | |
| 265 data.add(event); | |
| 266 } | |
| 267 | |
| 268 void addError(errorEvent, [StackTrace stackTrace]) { | |
| 269 throw 'addError($errorEvent, $stackTrace)'; | |
| 270 } | |
| 271 | |
| 272 void close() { | |
| 273 if (data != null) { | |
| 274 onClose(data.join()); | |
| 275 data = null; | |
| 276 } | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 SourceFile getSourceFile(api.CompilerInput provider, Uri uri) { | |
| 281 if (provider is SourceFileProvider) { | |
| 282 return provider.getSourceFile(uri); | |
| 283 } else { | |
| 284 return null; | |
| 285 } | |
| 286 } | |
| OLD | NEW |