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 |