Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 } | |
| OLD | NEW |