Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: pkg/fasta/lib/src/kernel/kernel_target.dart

Issue 2623033007: Fasta targets and loaders. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart 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 file.
4
5 library fasta.kernel_target;
6
7 import 'dart:async' show
8 Future;
9
10 import 'dart:io' show
11 File,
12 IOSink;
13
14 import 'package:kernel/ast.dart' show
15 Arguments,
16 AsyncMarker,
17 Class,
18 Constructor,
19 EmptyStatement,
20 Expression,
21 ExpressionStatement,
22 Field,
23 FieldInitializer,
24 FunctionNode,
25 Initializer,
26 InvalidInitializer,
27 Library,
28 Name,
29 NamedExpression,
30 NullLiteral,
31 Procedure,
32 ProcedureKind,
33 Program,
34 RedirectingInitializer,
35 ReturnStatement,
36 StaticGet,
37 StringLiteral,
38 SuperInitializer,
39 Throw,
40 VariableDeclaration,
41 VariableGet,
42 VoidType;
43
44 import 'package:kernel/binary/ast_to_binary.dart' show
45 BinaryPrinter;
46
47 import 'package:kernel/text/ast_to_text.dart' show
48 Printer;
49
50 import 'package:kernel/transformations/mixin_full_resolution.dart' show
51 MixinFullResolution,
52 SuperInitializerResolutionTransformer;
53
54 import '../source/source_loader.dart' show
55 SourceLoader;
56
57 import '../source/source_class_builder.dart' show
58 SourceClassBuilder;
59
60 import '../target_implementation.dart' show
61 TargetImplementation;
62
63 import '../translate_uri.dart' show
64 TranslateUri;
65
66 import '../dill/dill_target.dart' show
67 DillTarget;
68
69 import '../dill/dill_member_builder.dart' show
70 DillMemberBuilder;
71
72 import '../ast_kind.dart' show
73 AstKind;
74
75 import '../errors.dart' show
76 InputError,
77 internalError,
78 reportCrash,
79 resetCrashReporting;
80
81 import 'kernel_builder.dart' show
82 Builder,
83 ClassBuilder,
84 DynamicTypeBuilder,
85 InterfaceTypeBuilder,
86 InvalidTypeBuilder,
87 KernelClassBuilder,
88 KernelInterfaceTypeBuilder,
89 KernelLibraryBuilder,
90 KernelProcedureBuilder,
91 LibraryBuilder,
92 MixinApplicationBuilder,
93 NamedMixinApplicationBuilder,
94 TypeBuilder;
95
96 class KernelSourceTarget extends TargetImplementation {
97 final DillTarget dillTarget;
98 SourceLoader<Library> loader;
99 Program program;
100
101 final List errors = [];
102
103 KernelSourceTarget(DillTarget dillTarget, TranslateUri uriTranslator)
104 : dillTarget = dillTarget,
105 super(dillTarget.ticker, uriTranslator) {
106 resetCrashReporting();
107 loader = new SourceLoader<Library>(this);
108 }
109
110 void read(Uri uri) {
111 loader.read(uri);
112 }
113
114 LibraryBuilder createLibraryBuilder(Uri uri) {
115 if (dillTarget.isLoaded) {
116 var builder = dillTarget.loader.builders[uri];
117 if (builder != null) {
118 return builder;
119 }
120 }
121 return new KernelLibraryBuilder(uri, loader);
122 }
123
124 void addDirectSupertype(ClassBuilder cls, Set<ClassBuilder> set) {
125 if (cls == null) return;
126 TypeBuilder supertype = cls.supertype;
127 add(InterfaceTypeBuilder type) {
128 Builder builder = type.builder;
129 if (builder is ClassBuilder) {
130 set.add(builder);
131 } else if (builder is! InvalidTypeBuilder &&
132 builder is! DynamicTypeBuilder) {
133 internalError("Unhandled: ${builder.runtimeType}");
134 }
135 }
136 if (supertype == null) {
137 // OK.
138 } else if (supertype is MixinApplicationBuilder) {
139 add(supertype.supertype);
140 for (InterfaceTypeBuilder t in supertype.mixins) {
141 add(t);
142 }
143 } else if (supertype is InterfaceTypeBuilder) {
144 add(supertype);
145 } else {
146 internalError("Unhandled: ${supertype.runtimeType}");
147 }
148 if (cls.interfaces != null) {
149 for (InterfaceTypeBuilder t in cls.interfaces) {
150 add(t);
151 }
152 }
153 }
154
155 List<ClassBuilder> collectAllClasses() {
156 List<ClassBuilder> result = <ClassBuilder>[];
157 loader.builders.forEach((Uri uri, LibraryBuilder library) {
158 library.members.forEach((String name, Builder member) {
159 if (member is KernelClassBuilder) {
160 result.add(member);
161 }
162 });
163 // TODO(ahe): Translate this if needed:
164 // if (library is KernelLibraryBuilder) {
165 // result.addAll(library.mixinApplicationClasses);
166 // }
167 });
168 return result;
169 }
170
171 List<SourceClassBuilder> collectAllSourceClasses() {
172 List<SourceClassBuilder> result = <SourceClassBuilder>[];
173 loader.builders.forEach((Uri uri, LibraryBuilder library) {
174 library.members.forEach((String name, Builder member) {
175 if (member is SourceClassBuilder) {
176 result.add(member);
177 }
178 });
179 });
180 return result;
181 }
182
183 List<Class> collectAllMixinApplications() {
184 List<Class> result = <Class>[];
185 loader.builders.forEach((Uri uri, LibraryBuilder library) {
186 if (library is KernelLibraryBuilder) {
187 result.addAll(library.mixinApplicationClasses);
188 }
189 });
190 return result;
191 }
192
193 void breakCycle(ClassBuilder builder) {
194 Class cls = builder.target;
195 cls.implementedTypes.clear();
196 cls.supertype = null;
197 cls.mixedInType = null;
198 builder.supertype = new KernelInterfaceTypeBuilder("Object", null)
199 ..builder = objectClassBuilder;
200 builder.interfaces = null;
201 }
202
203 Future<Program> handleInputError(Uri uri, InputError error,
204 {bool isFullProgram}) {
205 if (error != null) {
206 String message = error.format();
207 print(message);
208 errors.add(message);
209 }
210 program = erroneousProgram();
211 return uri == null
212 ? new Future<Program>.value(program)
213 : writeLinkedProgram(uri, program, isFullProgram: isFullProgram);
214 }
215
216 Future<Program> writeProgram(Uri uri, AstKind astKind) async {
217 if (loader.first == null) return null;
218 if (errors.isNotEmpty) {
219 return handleInputError(uri, null, isFullProgram: true);
220 }
221 try {
222 if (astKind == AstKind.Analyzer) {
223 loader.buildElementStore();
224 } else {
225 loader.computeHierarchy(program);
226 }
227 await loader.buildBodies(astKind);
228 loader.finishStaticInvocations();
229 finishAllConstructors();
230 transformMixinApplications();
231 errors.addAll(loader.collectCompileTimeErrors().map((e) => e.format()));
232 if (errors.isNotEmpty) {
233 return handleInputError(uri, null, isFullProgram: true);
234 }
235 if (uri == null) return program;
236 return await writeLinkedProgram(uri, program, isFullProgram: true);
237 } on InputError catch (e) {
238 return handleInputError(uri, e, isFullProgram: true);
239 } catch (e, s) {
240 return reportCrash(e, s, loader?.currentUriForCrashReporting);
241 }
242 }
243
244 Future<Program> writeOutline(Uri uri) async {
245 if (loader.first == null) return null;
246 try {
247 await loader.buildOutlines();
248 loader.resolveParts();
249 loader.computeLibraryScopes();
250 loader.resolveTypes();
251 loader.convertConstructors();
252 loader.buildProgram();
253 loader.checkSemantics();
254 List<SourceClassBuilder> sourceClasses = collectAllSourceClasses();
255 installDefaultSupertypes(sourceClasses);
256 installDefaultConstructors(sourceClasses);
257 loader.resolveConstructors();
258 program = link(new List<Library>.from(loader.libraries));
259 if (uri == null) return program;
260 return await writeLinkedProgram(uri, program, isFullProgram: false);
261 } on InputError catch (e) {
262 return handleInputError(uri, e, isFullProgram: false);
263 } catch (e, s) {
264 return reportCrash(e, s, loader?.currentUriForCrashReporting);
265 }
266 }
267
268 Program erroneousProgram() {
269 Uri uri = loader.first?.uri ?? Uri.parse("error:error");
270 KernelLibraryBuilder library = new KernelLibraryBuilder(uri, loader);
271 KernelProcedureBuilder mainBuilder = new KernelProcedureBuilder(null, 0,
272 null, "main", null, null, AsyncMarker.Sync, ProcedureKind.Method);
273 library.addBuilder(mainBuilder.name, mainBuilder);
274 loader.first = library;
275 mainBuilder.body = new ExpressionStatement(
276 new Throw(new StringLiteral("${errors.join('\n')}")));
277 library.build();
278 return link(<Library>[library.library]);
279 }
280
281 Program link(List<Library> libraries) {
Johnni Winther 2017/01/19 09:21:33 Add dartdoc to this method.
ahe 2017/01/19 10:48:30 Done.
282 Map<String, List<int>> uriToLineStarts = <String, List<int>>{};
283
284 // for (Library library in libraries) {
285 // // TODO(ahe): Compute line starts instead.
286 // uriToLineStarts[library.fileUri] = <int>[0];
287 // }
288
289 final Program binary = dillTarget.loader.program;
290 if (binary != null) {
291 libraries.addAll(binary.libraries);
292 uriToLineStarts.addAll(binary.uriToLineStarts);
293 }
294
295 // TODO(ahe): Remove this line. Kernel seems to generate a default line map
296 // that used when there's no fileUri on an element. Instead, ensure all
297 // elements have a fileUri.
298 uriToLineStarts[""] = <int>[0];
299 Program program = new Program(libraries, uriToLineStarts);
300 if (loader.first != null) {
301 Builder builder = loader.first.members["main"];
302 if (builder is KernelProcedureBuilder) {
303 program.mainMethod = builder.procedure;
304 }
305 }
306 // TODO(ahe): This is kinda hackish. Use the transformer instead.
307 LibraryBuilder builtin =
308 dillTarget.loader.builders[Uri.parse("dart:_builtin")];
309 if (builtin != null) {
310 DillMemberBuilder builder = builtin.members["_getMainClosure"];
311 if (builder != null) {
312 Expression getMain = program.mainMethod == null
313 ? new Throw(new StringLiteral("No main method."))
314 : new StaticGet(program.mainMethod);
315 Procedure procedure = builder.member;
316 procedure.function = new FunctionNode(new ReturnStatement(getMain));
317 procedure.function.parent = procedure;
318 }
319 }
320 ticker.logMs("Linked program");
321 return program;
322 }
323
324 Future<Program> writeLinkedProgram(Uri uri, Program program,
325 {bool isFullProgram}) async {
326 File output = new File.fromUri(uri);
327 IOSink sink = output.openWrite();
328 try {
329 new BinaryPrinter(sink).writeProgramFile(program);
330 } finally {
331 await sink.close();
332 }
333 if (isFullProgram) {
334 ticker.logMs("Wrote program to ${uri.toFilePath()}");
335 } else {
336 ticker.logMs("Wrote outline to ${uri.toFilePath()}");
337 }
338 return null;
339 }
340
341 void installDefaultSupertypes(List<SourceClassBuilder> builders) {
342 Class objectClass = this.objectClass;
343 for (SourceClassBuilder builder in builders) {
344 Class cls = builder.target;
345 if (cls != objectClass) {
346 cls.supertype ??= objectClass.asRawSupertype;
347 }
348 }
349 ticker.logMs("Installed Object as implicit superclass");
350 }
351
352 void installDefaultConstructors(List<SourceClassBuilder> builders) {
353 Class objectClass = this.objectClass;
354 for (SourceClassBuilder builder in builders) {
355 if (builder.target != objectClass) {
356 installDefaultConstructor(builder);
357 }
358 }
359 ticker.logMs("Installed default constructors");
360 }
361
362 KernelClassBuilder get objectClassBuilder {
363 return loader.coreLibrary.exports["Object"];
364 }
365
366 Class get objectClass => objectClassBuilder.cls;
367
368 /// If [builder] doesn't have a constructors, install the defaults.
369 void installDefaultConstructor(SourceClassBuilder builder) {
370 if (!builder.constructors.isEmpty) return;
371 /// Quotes below are from [Dart Programming Language Specification, 4th
372 /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/EC MA-408.pdf):
373 if (builder is NamedMixinApplicationBuilder) {
374 /// >A mixin application of the form S with M; defines a class C with
375 /// >superclass S.
376 /// >...
377
378 /// >Let LM be the library in which M is declared. For each generative
379 /// >constructor named qi(Ti1 ai1, . . . , Tiki aiki), i in 1..n of S
380 /// >that is accessible to LM , C has an implicitly declared constructor
381 /// >named q'i = [C/S]qi of the form q'i(ai1,...,aiki) :
382 /// >super(ai1,...,aiki);.
383 Builder supertype = builder;
384 while (supertype is NamedMixinApplicationBuilder) {
385 NamedMixinApplicationBuilder named = supertype;
386 TypeBuilder type = named.mixinApplication;
387 if (type is MixinApplicationBuilder) {
388 MixinApplicationBuilder t = type;
389 type = t.supertype;
390 }
391 if (type is InterfaceTypeBuilder) {
392 supertype = type.builder;
393 } else {
394 internalError("Unhandled: ${type.runtimeType}");
395 }
396 }
397 if (supertype is KernelClassBuilder) {
398 for (Constructor constructor in supertype.cls.constructors) {
399 builder.addSyntheticConstructor(
400 makeMixinApplicationConstructor(builder.cls.mixin, constructor));
401 }
402 } else {
403 internalError("Unhandled: ${supertype.runtimeType}");
404 }
405 } else {
406 /// >Iff no constructor is specified for a class C, it implicitly has a
407 /// >default constructor C() : super() {}, unless C is class Object.
408 // The superinitializer is installed below in [finishConstructors].
409 builder.addSyntheticConstructor(makeDefaultConstructor());
410 }
411 }
412
413 Constructor makeMixinApplicationConstructor(
414 Class mixin, Constructor constructor) {
415 VariableDeclaration copyFormal(VariableDeclaration formal) {
416 // TODO(ahe): Handle initializers.
417 return new VariableDeclaration(formal.name,
418 type: formal.type, isFinal: formal.isFinal, isConst: formal.isConst);
419 }
420 List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
421 List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
422 List<Expression> positional = <Expression>[];
423 List<NamedExpression> named = <NamedExpression>[];
424 for (VariableDeclaration formal in
425 constructor.function.positionalParameters) {
426 positionalParameters.add(copyFormal(formal));
427 positional.add(new VariableGet(positionalParameters.last));
428 }
429 for (VariableDeclaration formal in
430 constructor.function.namedParameters) {
431 namedParameters.add(copyFormal(formal));
432 named.add(new NamedExpression(
433 formal.name, new VariableGet(namedParameters.last)));
434 }
435 FunctionNode function = new FunctionNode(new EmptyStatement(),
436 positionalParameters: positionalParameters,
437 namedParameters: namedParameters,
438 requiredParameterCount: constructor.function.requiredParameterCount,
439 returnType: const VoidType());
440 SuperInitializer initializer = new SuperInitializer(
441 constructor, new Arguments(positional, named: named));
442 return new Constructor(function,
443 name: constructor.name,
444 initializers: <Initializer>[initializer]);
445 }
446
447 Constructor makeDefaultConstructor() {
448 return new Constructor(
449 new FunctionNode(new EmptyStatement(), returnType: const VoidType()),
450 name: new Name(""));
451 }
452
453 void finishAllConstructors() {
454 Class objectClass = this.objectClass;
455 for (SourceClassBuilder builder in collectAllSourceClasses()) {
456 Class cls = builder.target;
457 if (cls != objectClass) {
458 finishConstructors(cls);
459 }
460 }
461 ticker.logMs("Finished constructors");
462 }
463
464 /// Ensure constructors of [cls] have the correct initializers and other
465 /// requirements.
466 void finishConstructors(Class cls) {
467 /// Quotes below are from [Dart Programming Language Specification, 4th
468 /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/EC MA-408.pdf):
469 Constructor superTarget;
470 List<Field> uninitializedFields = <Field>[];
471 for (Field field in cls.fields) {
472 if (field.initializer == null) {
473 uninitializedFields.add(field);
474 }
475 }
476 Map<Constructor, List<FieldInitializer>> fieldInitializers =
477 <Constructor, List<FieldInitializer>>{};
478 for (Constructor constructor in cls.constructors) {
479 if (!isRedirectingGenerativeConstructor(constructor)) {
480 /// >If no superinitializer is provided, an implicit superinitializer
481 /// >of the form super() is added at the end of k’s initializer list,
482 /// >unless the enclosing class is class Object.
483 if (!constructor.initializers.any(isSuperinitializerOrInvalid)) {
484 superTarget ??= defaultSuperConstructor(cls);
485 Initializer initializer;
486 if (superTarget == null) {
487 initializer = new InvalidInitializer();
488 } else {
489 initializer =
490 new SuperInitializer(superTarget, new Arguments.empty());
491 }
492 constructor.initializers.add(initializer);
493 initializer.parent = constructor;
494 }
495 if (constructor.function.body == null) {
496 /// >If a generative constructor c is not a redirecting constructor
497 /// >and no body is provided, then c implicitly has an empty body {}.
498 /// We use an empty statement instead.
499 constructor.function.body = new EmptyStatement();
500 constructor.function.body.parent = constructor.function;
501 }
502 List<FieldInitializer> myFieldInitializers = <FieldInitializer>[];
503 for (Initializer initializer in constructor.initializers) {
504 if (initializer is FieldInitializer) {
505 myFieldInitializers.add(initializer);
506 }
507 }
508 fieldInitializers[constructor] = myFieldInitializers;
509 }
510 }
511 Set<Field> initializedFields;
512 fieldInitializers.forEach(
513 (Constructor constructor, List<FieldInitializer> initializers) {
514 Iterable<Field> fields = initializers.map((i) => i.field);
515 if (initializedFields == null) {
516 initializedFields = new Set<Field>.from(fields);
517 } else {
518 initializedFields.addAll(fields);
519 }
520 });
521 for (Field field in uninitializedFields) {
Johnni Winther 2017/01/19 09:21:34 Add a comment to this and the next loop. The diffe
ahe 2017/01/19 10:48:30 Done.
522 if (initializedFields == null || !initializedFields.contains(field)) {
523 field.initializer = new NullLiteral()
524 ..parent = field;
525 }
526 }
527 fieldInitializers.forEach(
528 (Constructor constructor, List<FieldInitializer> initializers) {
529 Iterable<Field> fields = initializers.map((i) => i.field);
530 for (Field field in initializedFields.difference(fields.toSet())) {
531 if (field.initializer == null) {
532 FieldInitializer initializer =
533 new FieldInitializer(field, new NullLiteral());
534 initializer.parent = constructor;
535 constructor.initializers.insert(0, initializer);
536 }
537 }
538 });
539 }
540
541 void transformMixinApplications() {
542 new MixinFullResolution().transform(program);
543 ticker.logMs("Transformed mixin applications");
544 }
545
546 void transformMixinApplicationsX() {
Johnni Winther 2017/01/19 09:21:34 Is this used?
ahe 2017/01/19 10:48:30 No. Removed.
547 MixinFullResolution transformer = new MixinFullResolution()
548 ..hierarchy = loader.hierarchy
549 ..coreTypes = loader.coreTypes;
550 Set<Class> transformedClasses = new Set<Class>();
551 Set<Class> processedClasses = new Set<Class>();
552 for (Class cls in collectAllMixinApplications()) {
553 transformer.transformClass(processedClasses, transformedClasses, cls);
554 }
555
556 for (SourceClassBuilder builder in collectAllSourceClasses()) {
557 Class cls = builder.target;
558 if (transformedClasses.contains(cls.superclass)) {
559 for (Constructor constructor in cls.constructors) {
560 new SuperInitializerResolutionTransformer(cls.superclass)
561 .transformInitializers(constructor.initializers);
562 }
563 }
564
565 }
566 ticker.logMs("Transformed mixin applications");
567 }
568
569 void dumpIr() {
570 StringBuffer sb = new StringBuffer();
571 for (Library library in loader.libraries) {
572 Printer printer = new Printer(sb);
573 printer.writeLibraryFile(library);
574 }
575 print("$sb");
576 }
577 }
578
579 bool isSuperinitializerOrInvalid(Initializer initializer) {
580 return initializer is SuperInitializer
581 || initializer is InvalidInitializer;
582 }
583
584 bool isRedirectingGenerativeConstructor(Constructor constructor) {
585 List<Initializer> initializers = constructor.initializers;
586 return initializers.length == 1
587 && initializers.single is RedirectingInitializer;
588 }
589
590 Constructor defaultSuperConstructor(Class cls) {
Johnni Winther 2017/01/19 09:21:34 Add dartdoc that this return a constructor that ca
ahe 2017/01/19 10:48:30 Done.
591 Class superclass = cls.superclass;
592 while (superclass != null && superclass.isMixinApplication) {
593 superclass = superclass.superclass;
594 }
595 for (Constructor constructor in superclass.constructors) {
596 if (constructor.name.name.isEmpty) {
597 return constructor.function.requiredParameterCount == 0 ?
598 constructor : null;
599 }
600 }
601 return null;
602 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698