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

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

Issue 2623033007: Fasta targets and loaders. (Closed)
Patch Set: Address review comments. 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
« no previous file with comments | « pkg/fasta/lib/src/dill/dill_target.dart ('k') | pkg/fasta/lib/src/loader.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /// Creates a program by combining [libraries] with the libraries of
282 /// `dillTarget.loader.program`.
283 Program link(List<Library> libraries) {
284 Map<String, List<int>> uriToLineStarts = <String, List<int>>{};
285
286 // for (Library library in libraries) {
287 // // TODO(ahe): Compute line starts instead.
288 // uriToLineStarts[library.fileUri] = <int>[0];
289 // }
290
291 final Program binary = dillTarget.loader.program;
292 if (binary != null) {
293 libraries.addAll(binary.libraries);
294 uriToLineStarts.addAll(binary.uriToLineStarts);
295 }
296
297 // TODO(ahe): Remove this line. Kernel seems to generate a default line map
298 // that used when there's no fileUri on an element. Instead, ensure all
299 // elements have a fileUri.
300 uriToLineStarts[""] = <int>[0];
301 Program program = new Program(libraries, uriToLineStarts);
302 if (loader.first != null) {
303 Builder builder = loader.first.members["main"];
304 if (builder is KernelProcedureBuilder) {
305 program.mainMethod = builder.procedure;
306 }
307 }
308 // TODO(ahe): This is kinda hackish. Use the transformer instead.
309 LibraryBuilder builtin =
310 dillTarget.loader.builders[Uri.parse("dart:_builtin")];
311 if (builtin != null) {
312 DillMemberBuilder builder = builtin.members["_getMainClosure"];
313 if (builder != null) {
314 Expression getMain = program.mainMethod == null
315 ? new Throw(new StringLiteral("No main method."))
316 : new StaticGet(program.mainMethod);
317 Procedure procedure = builder.member;
318 procedure.function = new FunctionNode(new ReturnStatement(getMain));
319 procedure.function.parent = procedure;
320 }
321 }
322 ticker.logMs("Linked program");
323 return program;
324 }
325
326 Future<Program> writeLinkedProgram(Uri uri, Program program,
327 {bool isFullProgram}) async {
328 File output = new File.fromUri(uri);
329 IOSink sink = output.openWrite();
330 try {
331 new BinaryPrinter(sink).writeProgramFile(program);
332 } finally {
333 await sink.close();
334 }
335 if (isFullProgram) {
336 ticker.logMs("Wrote program to ${uri.toFilePath()}");
337 } else {
338 ticker.logMs("Wrote outline to ${uri.toFilePath()}");
339 }
340 return null;
341 }
342
343 void installDefaultSupertypes(List<SourceClassBuilder> builders) {
344 Class objectClass = this.objectClass;
345 for (SourceClassBuilder builder in builders) {
346 Class cls = builder.target;
347 if (cls != objectClass) {
348 cls.supertype ??= objectClass.asRawSupertype;
349 }
350 }
351 ticker.logMs("Installed Object as implicit superclass");
352 }
353
354 void installDefaultConstructors(List<SourceClassBuilder> builders) {
355 Class objectClass = this.objectClass;
356 for (SourceClassBuilder builder in builders) {
357 if (builder.target != objectClass) {
358 installDefaultConstructor(builder);
359 }
360 }
361 ticker.logMs("Installed default constructors");
362 }
363
364 KernelClassBuilder get objectClassBuilder {
365 return loader.coreLibrary.exports["Object"];
366 }
367
368 Class get objectClass => objectClassBuilder.cls;
369
370 /// If [builder] doesn't have a constructors, install the defaults.
371 void installDefaultConstructor(SourceClassBuilder builder) {
372 if (!builder.constructors.isEmpty) return;
373 /// Quotes below are from [Dart Programming Language Specification, 4th
374 /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/EC MA-408.pdf):
375 if (builder is NamedMixinApplicationBuilder) {
376 /// >A mixin application of the form S with M; defines a class C with
377 /// >superclass S.
378 /// >...
379
380 /// >Let LM be the library in which M is declared. For each generative
381 /// >constructor named qi(Ti1 ai1, . . . , Tiki aiki), i in 1..n of S
382 /// >that is accessible to LM , C has an implicitly declared constructor
383 /// >named q'i = [C/S]qi of the form q'i(ai1,...,aiki) :
384 /// >super(ai1,...,aiki);.
385 Builder supertype = builder;
386 while (supertype is NamedMixinApplicationBuilder) {
387 NamedMixinApplicationBuilder named = supertype;
388 TypeBuilder type = named.mixinApplication;
389 if (type is MixinApplicationBuilder) {
390 MixinApplicationBuilder t = type;
391 type = t.supertype;
392 }
393 if (type is InterfaceTypeBuilder) {
394 supertype = type.builder;
395 } else {
396 internalError("Unhandled: ${type.runtimeType}");
397 }
398 }
399 if (supertype is KernelClassBuilder) {
400 for (Constructor constructor in supertype.cls.constructors) {
401 builder.addSyntheticConstructor(
402 makeMixinApplicationConstructor(builder.cls.mixin, constructor));
403 }
404 } else {
405 internalError("Unhandled: ${supertype.runtimeType}");
406 }
407 } else {
408 /// >Iff no constructor is specified for a class C, it implicitly has a
409 /// >default constructor C() : super() {}, unless C is class Object.
410 // The superinitializer is installed below in [finishConstructors].
411 builder.addSyntheticConstructor(makeDefaultConstructor());
412 }
413 }
414
415 Constructor makeMixinApplicationConstructor(
416 Class mixin, Constructor constructor) {
417 VariableDeclaration copyFormal(VariableDeclaration formal) {
418 // TODO(ahe): Handle initializers.
419 return new VariableDeclaration(formal.name,
420 type: formal.type, isFinal: formal.isFinal, isConst: formal.isConst);
421 }
422 List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
423 List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
424 List<Expression> positional = <Expression>[];
425 List<NamedExpression> named = <NamedExpression>[];
426 for (VariableDeclaration formal in
427 constructor.function.positionalParameters) {
428 positionalParameters.add(copyFormal(formal));
429 positional.add(new VariableGet(positionalParameters.last));
430 }
431 for (VariableDeclaration formal in
432 constructor.function.namedParameters) {
433 namedParameters.add(copyFormal(formal));
434 named.add(new NamedExpression(
435 formal.name, new VariableGet(namedParameters.last)));
436 }
437 FunctionNode function = new FunctionNode(new EmptyStatement(),
438 positionalParameters: positionalParameters,
439 namedParameters: namedParameters,
440 requiredParameterCount: constructor.function.requiredParameterCount,
441 returnType: const VoidType());
442 SuperInitializer initializer = new SuperInitializer(
443 constructor, new Arguments(positional, named: named));
444 return new Constructor(function,
445 name: constructor.name,
446 initializers: <Initializer>[initializer]);
447 }
448
449 Constructor makeDefaultConstructor() {
450 return new Constructor(
451 new FunctionNode(new EmptyStatement(), returnType: const VoidType()),
452 name: new Name(""));
453 }
454
455 void finishAllConstructors() {
456 Class objectClass = this.objectClass;
457 for (SourceClassBuilder builder in collectAllSourceClasses()) {
458 Class cls = builder.target;
459 if (cls != objectClass) {
460 finishConstructors(cls);
461 }
462 }
463 ticker.logMs("Finished constructors");
464 }
465
466 /// Ensure constructors of [cls] have the correct initializers and other
467 /// requirements.
468 void finishConstructors(Class cls) {
469 /// Quotes below are from [Dart Programming Language Specification, 4th
470 /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/EC MA-408.pdf):
471 Constructor superTarget;
472 List<Field> uninitializedFields = <Field>[];
473 for (Field field in cls.fields) {
474 if (field.initializer == null) {
475 uninitializedFields.add(field);
476 }
477 }
478 Map<Constructor, List<FieldInitializer>> fieldInitializers =
479 <Constructor, List<FieldInitializer>>{};
480 for (Constructor constructor in cls.constructors) {
481 if (!isRedirectingGenerativeConstructor(constructor)) {
482 /// >If no superinitializer is provided, an implicit superinitializer
483 /// >of the form super() is added at the end of k’s initializer list,
484 /// >unless the enclosing class is class Object.
485 if (!constructor.initializers.any(isSuperinitializerOrInvalid)) {
486 superTarget ??= defaultSuperConstructor(cls);
487 Initializer initializer;
488 if (superTarget == null) {
489 initializer = new InvalidInitializer();
490 } else {
491 initializer =
492 new SuperInitializer(superTarget, new Arguments.empty());
493 }
494 constructor.initializers.add(initializer);
495 initializer.parent = constructor;
496 }
497 if (constructor.function.body == null) {
498 /// >If a generative constructor c is not a redirecting constructor
499 /// >and no body is provided, then c implicitly has an empty body {}.
500 /// We use an empty statement instead.
501 constructor.function.body = new EmptyStatement();
502 constructor.function.body.parent = constructor.function;
503 }
504 List<FieldInitializer> myFieldInitializers = <FieldInitializer>[];
505 for (Initializer initializer in constructor.initializers) {
506 if (initializer is FieldInitializer) {
507 myFieldInitializers.add(initializer);
508 }
509 }
510 fieldInitializers[constructor] = myFieldInitializers;
511 }
512 }
513 Set<Field> initializedFields;
514 fieldInitializers.forEach(
515 (Constructor constructor, List<FieldInitializer> initializers) {
516 Iterable<Field> fields = initializers.map((i) => i.field);
517 if (initializedFields == null) {
518 initializedFields = new Set<Field>.from(fields);
519 } else {
520 initializedFields.addAll(fields);
521 }
522 });
523 // Run through all fields that aren't initialized by any constructor, and
524 // set their initializer to `null`.
525 for (Field field in uninitializedFields) {
526 if (initializedFields == null || !initializedFields.contains(field)) {
527 field.initializer = new NullLiteral()
528 ..parent = field;
529 }
530 }
531 // Run through all fields that are initialized by some constructor, and
532 // make sure that all other constructors also initialize them.
533 fieldInitializers.forEach(
534 (Constructor constructor, List<FieldInitializer> initializers) {
535 Iterable<Field> fields = initializers.map((i) => i.field);
536 for (Field field in initializedFields.difference(fields.toSet())) {
537 if (field.initializer == null) {
538 FieldInitializer initializer =
539 new FieldInitializer(field, new NullLiteral());
540 initializer.parent = constructor;
541 constructor.initializers.insert(0, initializer);
542 }
543 }
544 });
545 }
546
547 void transformMixinApplications() {
548 new MixinFullResolution().transform(program);
549 ticker.logMs("Transformed mixin applications");
550 }
551
552 void dumpIr() {
553 StringBuffer sb = new StringBuffer();
554 for (Library library in loader.libraries) {
555 Printer printer = new Printer(sb);
556 printer.writeLibraryFile(library);
557 }
558 print("$sb");
559 }
560 }
561
562 bool isSuperinitializerOrInvalid(Initializer initializer) {
563 return initializer is SuperInitializer
564 || initializer is InvalidInitializer;
565 }
566
567 bool isRedirectingGenerativeConstructor(Constructor constructor) {
568 List<Initializer> initializers = constructor.initializers;
569 return initializers.length == 1
570 && initializers.single is RedirectingInitializer;
571 }
572
573 /// Looks for a constructor call that matches `super()` from a constructor in
574 /// [cls]. Such a constructor may have optional arguments, but no required
575 /// arguments.
576 Constructor defaultSuperConstructor(Class cls) {
577 Class superclass = cls.superclass;
578 while (superclass != null && superclass.isMixinApplication) {
579 superclass = superclass.superclass;
580 }
581 for (Constructor constructor in superclass.constructors) {
582 if (constructor.name.name.isEmpty) {
583 return constructor.function.requiredParameterCount == 0 ?
584 constructor : null;
585 }
586 }
587 return null;
588 }
OLDNEW
« no previous file with comments | « pkg/fasta/lib/src/dill/dill_target.dart ('k') | pkg/fasta/lib/src/loader.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698