Index: pkg/fasta/lib/src/kernel/kernel_library_builder.dart |
diff --git a/pkg/fasta/lib/src/kernel/kernel_library_builder.dart b/pkg/fasta/lib/src/kernel/kernel_library_builder.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c4f6748e7b997bf362d01d2347fd3d445b48771a |
--- /dev/null |
+++ b/pkg/fasta/lib/src/kernel/kernel_library_builder.dart |
@@ -0,0 +1,281 @@ |
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+library fasta.kernel_library_builder; |
+ |
+import 'package:kernel/ast.dart'; |
+ |
+import 'package:kernel/clone.dart' show |
+ CloneVisitor; |
+ |
+import '../errors.dart' show |
+ internalError; |
+ |
+import '../loader.dart' show |
+ Loader; |
+ |
+import '../modifier.dart' show |
+ staticMask; |
+ |
+import '../source/source_library_builder.dart' show |
+ SourceLibraryBuilder; |
+ |
+import '../source/source_class_builder.dart' show |
+ SourceClassBuilder; |
+ |
+import 'kernel_builder.dart' show |
+ Builder, |
+ ClassBuilder, |
+ ConstructorReferenceBuilder, |
+ DynamicTypeBuilder, |
+ EnumBuilder, |
+ FieldBuilder, |
+ FormalParameterBuilder, |
+ FunctionTypeAliasBuilder, |
+ KernelEnumBuilder, |
+ KernelFieldBuilder, |
+ KernelFormalParameterBuilder, |
+ KernelFunctionTypeAliasBuilder, |
+ KernelInterfaceTypeBuilder, |
+ KernelInvalidTypeBuilder, |
+ KernelMixinApplicationBuilder, |
+ KernelNamedMixinApplicationBuilder, |
+ KernelProcedureBuilder, |
+ KernelTypeBuilder, |
+ KernelTypeVariableBuilder, |
+ MemberBuilder, |
+ MetadataBuilder, |
+ MixedAccessor, |
+ NamedMixinApplicationBuilder, |
+ PrefixBuilder, |
+ ProcedureBuilder, |
+ TypeVariableBuilder; |
+ |
+class KernelLibraryBuilder |
+ extends SourceLibraryBuilder<KernelTypeBuilder, Library> { |
+ final Library library; |
+ |
+ final List<Class> mixinApplicationClasses = <Class>[]; |
+ |
+ final List<List> argumentsWithMissingDefaultValues = <List>[]; |
+ |
+ KernelLibraryBuilder(Uri uri, Loader loader) |
+ : library = new Library(uri), |
+ super(loader); |
+ |
+ Uri get uri => library.importUri; |
+ |
+ KernelTypeBuilder addInterfaceType(String name, |
+ List<KernelTypeBuilder> arguments) { |
+ KernelInterfaceTypeBuilder type = |
+ new KernelInterfaceTypeBuilder(name, arguments); |
+ if (identical(name, "dynamic")) { |
+ // TODO(ahe): Make const. |
+ type.builder = new DynamicTypeBuilder(const DynamicType()); |
+ } else { |
+ addType(type); |
+ } |
+ return type; |
+ } |
+ |
+ KernelTypeBuilder addMixinApplication(KernelTypeBuilder supertype, |
+ List<KernelTypeBuilder> mixins) { |
+ KernelTypeBuilder type = |
+ new KernelMixinApplicationBuilder(supertype, mixins); |
+ return addType(type); |
+ } |
+ |
+ KernelTypeBuilder addVoidType() { |
+ return new KernelInterfaceTypeBuilder("void", null); |
+ } |
+ |
+ ClassBuilder addClass(List<MetadataBuilder> metadata, |
+ int modifiers, String className, |
+ List<TypeVariableBuilder> typeVariables, KernelTypeBuilder supertype, |
+ List<KernelTypeBuilder> interfaces) { |
+ ClassBuilder cls = new SourceClassBuilder(metadata, modifiers, className, |
+ typeVariables, supertype, interfaces, classMembers, classTypes, this, |
+ new List<ConstructorReferenceBuilder>.from(constructorReferences)); |
+ constructorReferences.clear(); |
+ classMembers.forEach((String name, MemberBuilder builder) { |
+ while (builder != null) { |
+ builder.parent = cls; |
+ builder = builder.next; |
+ } |
+ }); |
+ // Nested scope began in `OutlineBuilder.beginClassDeclaration`. |
+ endNestedScope(); |
+ return addBuilder(className, cls); |
+ } |
+ |
+ NamedMixinApplicationBuilder addNamedMixinApplication( |
+ List<MetadataBuilder> metadata, String name, |
+ List<TypeVariableBuilder> typeVariables, int modifiers, |
+ KernelTypeBuilder mixinApplication, List<KernelTypeBuilder> interfaces) { |
+ NamedMixinApplicationBuilder builder = |
+ new KernelNamedMixinApplicationBuilder(metadata, name, typeVariables, |
+ modifiers, mixinApplication, interfaces, classTypes, this); |
+ // Nested scope began in `OutlineBuilder.beginNamedMixinApplication`. |
+ endNestedScope(); |
+ return addBuilder(name, builder); |
+ } |
+ |
+ FieldBuilder addField(List<MetadataBuilder> metadata, |
+ int modifiers, KernelTypeBuilder type, String name) { |
+ return addBuilder(name, |
+ new KernelFieldBuilder(metadata, type, name, modifiers)); |
+ } |
+ |
+ ProcedureBuilder addProcedure(List<MetadataBuilder> metadata, |
+ int modifiers, KernelTypeBuilder returnType, String name, |
+ List<TypeVariableBuilder> typeVariables, |
+ List<FormalParameterBuilder> formals, AsyncMarker asyncModifier, |
+ ProcedureKind kind) { |
+ return addBuilder(name, |
+ new KernelProcedureBuilder(metadata, modifiers, returnType, name, |
+ typeVariables, formals, asyncModifier, kind)); |
+ } |
+ |
+ void addFactoryMethod(List<MetadataBuilder> metadata, |
+ ConstructorReferenceBuilder constructorName, |
+ List<FormalParameterBuilder> formals, AsyncMarker asyncModifier, |
+ ConstructorReferenceBuilder redirectionTarget) { |
+ String name = constructorName.name; |
+ assert(constructorName.suffix == null); |
+ addBuilder(name, |
+ new KernelProcedureBuilder(metadata, staticMask, null, name, null, |
+ formals, asyncModifier, ProcedureKind.Factory, redirectionTarget)); |
+ } |
+ |
+ EnumBuilder addEnum(List<MetadataBuilder> metadata, String name, |
+ List<String> constants) { |
+ return addBuilder(name, |
+ new KernelEnumBuilder(metadata, name, constants, this)); |
+ } |
+ |
+ FunctionTypeAliasBuilder addFunctionTypeAlias(List<MetadataBuilder> metadata, |
+ KernelTypeBuilder returnType, String name, |
+ List<TypeVariableBuilder> typeVariables, |
+ List<FormalParameterBuilder> formals) { |
+ FunctionTypeAliasBuilder typedef = new KernelFunctionTypeAliasBuilder( |
+ metadata, returnType, name, typeVariables, formals, classTypes, this); |
+ // Nested scope began in `OutlineBuilder.beginFunctionTypeAlias`. |
+ endNestedScope(); |
+ return addBuilder(name, typedef); |
+ } |
+ |
+ KernelFormalParameterBuilder addFormalParameter( |
+ List<MetadataBuilder> metadata, int modifiers, |
+ KernelTypeBuilder type, String name, bool hasThis) { |
+ return new KernelFormalParameterBuilder( |
+ metadata, modifiers, type, name, hasThis); |
+ } |
+ |
+ KernelTypeVariableBuilder addTypeVariable(String name, |
+ KernelTypeBuilder bound) { |
+ return new KernelTypeVariableBuilder(name, bound); |
+ } |
+ |
+ void buildBuilder(Builder builder) { |
+ if (builder is SourceClassBuilder) { |
+ Class cls = builder.build(this); |
+ library.addClass(cls); |
+ Class superclass = cls.superclass; |
+ if (superclass != null && superclass.isMixinApplication) { |
+ List<Class> mixinApplications = <Class>[]; |
+ mixinApplicationClasses.add(cls); |
+ while (superclass != null && superclass.isMixinApplication) { |
+ if (superclass.parent == null) { |
+ mixinApplications.add(superclass); |
+ } |
+ superclass = superclass.superclass; |
+ } |
+ for (Class cls in mixinApplications.reversed) { |
+ // TODO(ahe): Should be able to move this into the above loop as long |
+ // as we don't care about matching dartk perfectly. |
+ library.addClass(cls); |
+ mixinApplicationClasses.add(cls); |
+ } |
+ } |
+ } else if (builder is KernelFieldBuilder) { |
+ library.addMember(builder.build(library)..isStatic = true); |
+ } else if (builder is KernelProcedureBuilder) { |
+ library.addMember(builder.build(library)..isStatic = true); |
+ } else if (builder is FunctionTypeAliasBuilder) { |
+ // Kernel discard typedefs and use their corresponding function types |
+ // directly. |
+ } else if (builder is KernelEnumBuilder) { |
+ library.addClass(builder.build(this)); |
+ } else if (builder is PrefixBuilder) { |
+ // Ignored. Kernel doesn't represent prefixes. |
+ } else { |
+ internalError("Unhandled builder: ${builder.runtimeType}"); |
+ } |
+ } |
+ |
+ Library build() { |
+ super.build(); |
+ library.name = name; |
+ // TODO(ahe): Set fileUri. |
+ // library.fileUri = "${fileUri ?? uri}"; |
+ return library; |
+ } |
+ |
+ Builder buildAmbiguousBuilder( |
+ String name, Builder builder, Builder other) { |
+ if (builder.next == null && other.next == null) { |
+ if (builder.isGetter && other.isSetter) { |
+ return new MixedAccessor(builder, other); |
+ } else if (builder.isSetter && other.isGetter) { |
+ return new MixedAccessor(other, builder); |
+ } |
+ } |
+ return new KernelInvalidTypeBuilder(name, this); |
+ } |
+ |
+ void addArgumentsWithMissingDefaultValues(Arguments arguments, |
+ FunctionNode function) { |
+ assert(partOfLibrary == null); |
+ argumentsWithMissingDefaultValues.add([arguments, function]); |
+ } |
+ |
+ int finishStaticInvocations() { |
+ CloneVisitor cloner; |
+ for (var list in argumentsWithMissingDefaultValues) { |
+ final Arguments arguments = list[0]; |
+ final FunctionNode function = list[1]; |
+ |
+ Expression defaultArgumentFrom(Expression expression) { |
+ if (expression == null) { |
+ return new NullLiteral(); |
+ } |
+ cloner ??= new CloneVisitor(); |
+ return cloner.clone(expression); |
+ } |
+ |
+ for (int i = function.requiredParameterCount; |
+ i < function.positionalParameters.length; |
+ i++) { |
+ arguments.positional[i] ??= |
+ defaultArgumentFrom(function.positionalParameters[i].initializer) |
+ ..parent = arguments; |
+ } |
+ Map<String, VariableDeclaration> names; |
+ for (NamedExpression expression in arguments.named) { |
+ if (expression.value == null) { |
+ if (names == null) { |
+ names = <String, VariableDeclaration>{}; |
+ for (VariableDeclaration parameter in function.namedParameters) { |
+ names[parameter.name] = parameter; |
+ } |
+ } |
+ expression.value = |
+ defaultArgumentFrom(names[expression.name].initializer) |
+ ..parent = expression; |
+ } |
+ } |
+ } |
+ return argumentsWithMissingDefaultValues.length; |
+ } |
+} |