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

Unified Diff: pkg/compiler/lib/src/resolution/type_resolver.dart

Issue 2567133002: Add support for the new function-type syntax. (Closed)
Patch Set: Fixes after rebase. Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/resolution/type_resolver.dart
diff --git a/pkg/compiler/lib/src/resolution/type_resolver.dart b/pkg/compiler/lib/src/resolution/type_resolver.dart
index 318e7488f429e86e8c8693d209a82407658f3935..34e5cab4dc2d1a45624868171b19b9f6f5bf6edb 100644
--- a/pkg/compiler/lib/src/resolution/type_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/type_resolver.dart
@@ -27,6 +27,16 @@ import 'registry.dart' show ResolutionRegistry;
import 'resolution_common.dart' show MappingVisitor;
import 'scope.dart' show Scope;
+class _FormalsTypeResolutionResult {
+ final List<ResolutionDartType> requiredTypes;
+ final List<ResolutionDartType> orderedTypes;
+ final List<String> names;
+ final List<ResolutionDartType> nameTypes;
+
+ _FormalsTypeResolutionResult(
+ this.requiredTypes, this.orderedTypes, this.names, this.nameTypes);
+}
+
class TypeResolver {
final Resolution resolution;
@@ -66,6 +76,154 @@ class TypeResolver {
ResolutionDartType resolveTypeAnnotation(
MappingVisitor visitor, TypeAnnotation node,
{bool malformedIsError: false, bool deferredIsMalformed: true}) {
+ return _resolveTypeAnnotation(
+ visitor, node, const [], malformedIsError: malformedIsError,
+ deferredIsMalformed: deferredIsMalformed);
+ }
+
+ // TODO(floitsch): the [visibleTypeParameterNames] is a hack to put
+ // type parameters in scope for the nested types.
+ //
+ // For example, in the following example, the generic type "A" would be stored
+ // in `visibleTypeParameterNames`.
+ // `typedef F = Function(List<A> Function<A>(A x))`.
+ //
+ // They are resolved to `dynamic` until dart2js supports generic methods.
+ ResolutionDartType _resolveTypeAnnotation(
+ MappingVisitor visitor, TypeAnnotation node,
+ List<List<String>> visibleTypeParameterNames,
+ {bool malformedIsError: false, bool deferredIsMalformed: true}) {
+
+ if (node.asNominalTypeAnnotation() != null) {
+ return resolveNominalTypeAnnotation(
+ visitor, node,
+ visibleTypeParameterNames,
+ malformedIsError: malformedIsError,
+ deferredIsMalformed: deferredIsMalformed);
+ }
+ assert(node.asFunctionTypeAnnotation() != null);
+ return _resolveFunctionTypeAnnotation(
+ visitor, node, visibleTypeParameterNames,
+ malformedIsError: malformedIsError,
+ deferredIsMalformed: deferredIsMalformed);
+ }
+
+ /// Resolves the types of a parameter list.
+ ///
+ /// This function does not accept "inline" function types. For example
+ /// `foo(int bar(String x))` is not accepted.
+ ///
+ /// However, it does work with nested generalized function types:
+ /// `foo(int Function(String) x)`.
+ _FormalsTypeResolutionResult _resolveFormalTypes(
+ MappingVisitor visitor, NodeList formals,
+ List<List<String>> visibleTypeParameterNames) {
+
+ ResolutionDartType resolvePositionalType(VariableDefinitions node) {
+ return _resolveTypeAnnotation(
+ visitor, node.type, visibleTypeParameterNames);
+ }
+
+ void fillNamedTypes(NodeList namedFormals,
+ List<String> names, List<ResolutionDartType> types) {
+ List<Node> nodes = namedFormals.nodes.toList(growable: false);
+
+ // Sort the named arguments first.
+ nodes.sort((node1, node2) {
+ VariableDefinitions a = node1;
+ VariableDefinitions b = node2;
+ assert(a.definitions.nodes.tail.isEmpty);
+ assert(b.definitions.nodes.tail.isEmpty);
+ return a.definitions.nodes.head.asIdentifier().source.compareTo(
+ b.definitions.nodes.head.asIdentifier().source);
+ });
+
+ for (VariableDefinitions node in nodes) {
+ String name = node.definitions.nodes.head.asIdentifier().source;
+ ResolutionDartType type = node.type == null
+ ? const ResolutionDynamicType()
+ : _resolveTypeAnnotation(
+ visitor, node.type, visibleTypeParameterNames);
+ names.add(name);
+ types.add(type);
+ }
+ }
+
+ List<ResolutionDartType> requiredTypes = <ResolutionDartType>[];
+ NodeList optionalFormals = null;
+ for (Link<Node> link = formals.nodes; !link.isEmpty; link = link.tail) {
+ if (link.tail.isEmpty && link.head is NodeList) {
+ optionalFormals = link.head;
+ break;
+ }
+ requiredTypes.add(resolvePositionalType(link.head));
+ }
+
+
+ List<ResolutionDartType> orderedTypes = const <ResolutionDartType>[];
+ List<String> names = const <String>[];
+ List<ResolutionDartType> namedTypes = const <ResolutionDartType>[];
+
+ if (optionalFormals != null) {
+ // This must be a list of optional arguments.
+ String value = optionalFormals.beginToken.stringValue;
+ if ((!identical(value, '[')) && (!identical(value, '{'))) {
+ reporter.internalError(optionalFormals, "expected optional parameters");
+ }
+ bool optionalParametersAreNamed = (identical(value, '{'));
+
+ if (optionalParametersAreNamed) {
+ names = <String>[];
+ namedTypes = <ResolutionDartType>[];
+ fillNamedTypes(optionalFormals, names, namedTypes);
+ } else {
+ orderedTypes = <ResolutionDartType>[];
+ for (Link<Node> link = optionalFormals.nodes;
+ !link.isEmpty;
+ link = link.tail) {
+ orderedTypes.add(resolvePositionalType(link.head));
+ }
+ }
+ }
+ return new _FormalsTypeResolutionResult(
+ requiredTypes, orderedTypes, names, namedTypes);
+ }
+
+ ResolutionFunctionType _resolveFunctionTypeAnnotation(MappingVisitor visitor,
+ FunctionTypeAnnotation node,
+ List<List<String>> visibleTypeParameterNames,
+ {bool malformedIsError: false, bool deferredIsMalformed: true}) {
+
+ assert(visibleTypeParameterNames != null);
+
+ if (node.typeParameters != null) {
+ List<String> newTypeNames = node.typeParameters.map((TypeVariable node) {
+ return node.name.asIdentifier().source;
+ }).toList();
+ visibleTypeParameterNames =
+ visibleTypeParameterNames.toList()..add(newTypeNames);
+ }
+
+ ResolutionDartType returnType = node.returnType == null
+ ? const ResolutionDynamicType()
+ : _resolveTypeAnnotation(visitor, node.returnType,
+ visibleTypeParameterNames);
+ var formalTypes =
+ _resolveFormalTypes(visitor, node.formals, visibleTypeParameterNames);
+ var result = new ResolutionFunctionType.generalized(
+ returnType,
+ formalTypes.requiredTypes,
+ formalTypes.orderedTypes,
+ formalTypes.names,
+ formalTypes.nameTypes);
+ visitor.registry.useType(node, result);
+ return result;
+ }
+
+ ResolutionDartType resolveNominalTypeAnnotation(MappingVisitor visitor,
+ NominalTypeAnnotation node,
+ List<List<String>> visibleTypeParameterNames,
+ {bool malformedIsError: false, bool deferredIsMalformed: true}) {
ResolutionRegistry registry = visitor.registry;
Identifier typeName;
@@ -74,7 +232,8 @@ class TypeResolver {
ResolutionDartType checkNoTypeArguments(ResolutionDartType type) {
List<ResolutionDartType> arguments = new List<ResolutionDartType>();
bool hasTypeArgumentMismatch = resolveTypeArguments(
- visitor, node, const <ResolutionDartType>[], arguments);
+ visitor, node, const <ResolutionDartType>[], arguments,
+ visibleTypeParameterNames);
if (hasTypeArgumentMismatch) {
return new MalformedType(
new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
@@ -106,9 +265,6 @@ class TypeResolver {
}
}
- Element element = resolveTypeName(prefixName, typeName, visitor.scope,
- deferredIsMalformed: deferredIsMalformed);
-
ResolutionDartType reportFailureAndCreateType(
MessageKind messageKind, Map messageArguments,
{ResolutionDartType userProvidedBadType,
@@ -128,14 +284,33 @@ class TypeResolver {
typeName.source, visitor.enclosingElement);
}
List<ResolutionDartType> arguments = <ResolutionDartType>[];
- resolveTypeArguments(
- visitor, node, const <ResolutionDartType>[], arguments);
+ resolveTypeArguments(visitor, node, const <ResolutionDartType>[],
+ arguments, visibleTypeParameterNames);
return new MalformedType(
erroneousElement, userProvidedBadType, arguments);
}
+ Element element;
+ // Resolve references to type names as dynamic.
+ // TODO(floitsch): this hackishly resolves generic function type arguments
+ // to dynamic.
+ if (prefixName == null &&
+ visibleTypeParameterNames.any((n) => n.contains(typeName.source))) {
+ type = const ResolutionDynamicType();
+ } else {
+ element = resolveTypeName(prefixName, typeName, visitor.scope,
+ deferredIsMalformed: deferredIsMalformed);
+ }
+
// Try to construct the type from the element.
- if (element == null) {
+ if (type != null) {
+ // Already assigned to through the visibleTypeParameterNames.
+ // Just make sure that it doesn't have type arguments.
+ if (node.typeArguments != null) {
+ reporter.reportWarningMessage(node.typeArguments.nodes.head,
+ MessageKind.ADDITIONAL_TYPE_ARGUMENT);
+ }
+ } else if (element == null) {
type = reportFailureAndCreateType(
MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName});
} else if (element.isAmbiguous) {
@@ -170,8 +345,9 @@ class TypeResolver {
resolver.ensureClassWillBeResolvedInternal(cls);
cls.computeType(resolution);
List<ResolutionDartType> arguments = <ResolutionDartType>[];
- bool hasTypeArgumentMismatch =
- resolveTypeArguments(visitor, node, cls.typeVariables, arguments);
+ bool hasTypeArgumentMismatch = resolveTypeArguments(
+ visitor, node, cls.typeVariables, arguments,
+ visibleTypeParameterNames);
if (hasTypeArgumentMismatch) {
type = new BadInterfaceType(
cls.declaration,
@@ -194,7 +370,8 @@ class TypeResolver {
typdef.computeType(resolution);
List<ResolutionDartType> arguments = <ResolutionDartType>[];
bool hasTypeArgumentMismatch = resolveTypeArguments(
- visitor, node, typdef.typeVariables, arguments);
+ visitor, node, typdef.typeVariables, arguments,
+ visibleTypeParameterNames);
if (hasTypeArgumentMismatch) {
type = new BadTypedefType(
typdef,
@@ -241,7 +418,7 @@ class TypeResolver {
}
/// Checks the type arguments of [type] against the type variable bounds.
- void checkTypeVariableBounds(TypeAnnotation node, GenericType type) {
+ void checkTypeVariableBounds(NominalTypeAnnotation node, GenericType type) {
void checkTypeVariableBound(_, ResolutionDartType typeArgument,
ResolutionTypeVariableType typeVariable, ResolutionDartType bound) {
if (!types.isSubtype(typeArgument, bound)) {
@@ -266,9 +443,10 @@ class TypeResolver {
*/
bool resolveTypeArguments(
MappingVisitor visitor,
- TypeAnnotation node,
+ NominalTypeAnnotation node,
List<ResolutionDartType> typeVariables,
- List<ResolutionDartType> arguments) {
+ List<ResolutionDartType> arguments,
+ List<List<String>> visibleTypeParameterNames) {
if (node.typeArguments == null) {
return false;
}
@@ -283,8 +461,8 @@ class TypeResolver {
typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
typeArgumentCountMismatch = true;
}
- ResolutionDartType argType =
- resolveTypeAnnotation(visitor, typeArguments.head);
+ ResolutionDartType argType = _resolveTypeAnnotation(
+ visitor, typeArguments.head, visibleTypeParameterNames);
// TODO(karlklose): rewrite to not modify [arguments].
arguments.add(argType);
}

Powered by Google App Engine
This is Rietveld 408576698