Chromium Code Reviews| Index: pkg/compiler/lib/src/js_backend/runtime_types.dart |
| diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart |
| index 9b54dcd33f539775817e284b82318634206d2440..5b8100ae2c50afb671a75a5702f661c15679880f 100644 |
| --- a/pkg/compiler/lib/src/js_backend/runtime_types.dart |
| +++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart |
| @@ -2,28 +2,46 @@ |
| // 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. |
| -part of js_backend.backend; |
| +library js_backend.runtime_types; |
| + |
| +import '../common_elements.dart' show CommonElements, ElementEnvironment; |
| +import '../elements/elements.dart' show ClassElement; |
| +import '../elements/entities.dart'; |
| +import '../elements/resolution_types.dart' |
| + show |
| + MalformedType, |
| + MethodTypeVariableType, |
| + ResolutionDartTypeVisitor, |
| + ResolutionTypedefType, |
| + Types; |
| +import '../elements/types.dart'; |
| +import '../js/js.dart' as jsAst; |
| +import '../js/js.dart' show js; |
| +import '../js_emitter/js_emitter.dart' show Emitter; |
| +import '../universe/world_builder.dart'; |
| +import '../world.dart' show ClosedWorld; |
| +import 'backend_usage.dart'; |
| +import 'namer.dart'; |
| /// For each class, stores the possible class subtype tests that could succeed. |
| abstract class TypeChecks { |
| /// Get the set of checks required for class [element]. |
| - Iterable<TypeCheck> operator [](ClassElement element); |
| + Iterable<TypeCheck> operator [](ClassEntity element); |
| /// Get the iterable for all classes that need type checks. |
| - Iterable<ClassElement> get classes; |
| + Iterable<ClassEntity> get classes; |
| } |
| -typedef jsAst.Expression OnVariableCallback( |
| - ResolutionTypeVariableType variable); |
| +typedef jsAst.Expression OnVariableCallback(TypeVariableType variable); |
| typedef bool ShouldEncodeTypedefCallback(ResolutionTypedefType variable); |
| /// Interface for the classes and methods that need runtime types. |
| abstract class RuntimeTypesNeed { |
| - bool classNeedsRti(ClassElement cls); |
| - bool classNeedsRtiField(ClassElement cls); |
| - bool methodNeedsRti(MethodElement function); |
| - bool localFunctionNeedsRti(LocalFunctionElement function); |
| - bool classUsesTypeVariableExpression(ClassElement cls); |
| + bool classNeedsRti(ClassEntity cls); |
| + bool classNeedsRtiField(ClassEntity cls); |
| + bool methodNeedsRti(FunctionEntity function); |
| + bool localFunctionNeedsRti(Local function); |
| + bool classUsesTypeVariableExpression(ClassEntity cls); |
| } |
| /// Interface for computing classes and methods that need runtime types. |
| @@ -63,44 +81,45 @@ abstract class RuntimeTypesChecks { |
| /// Return all classes that are referenced in the type of the function, i.e., |
| /// in the return type or the argument types. |
| - Set<ClassElement> getReferencedClasses(ResolutionFunctionType type); |
| + Set<ClassEntity> getReferencedClasses(FunctionType type); |
| /// Return all classes that are uses a type arguments. |
| - Set<ClassElement> getRequiredArgumentClasses(); |
| + Set<ClassEntity> getRequiredArgumentClasses(); |
| } |
| /// Interface for computing the needed runtime type checks. |
| abstract class RuntimeTypesChecksBuilder { |
| void registerTypeVariableBoundsSubtypeCheck( |
| - ResolutionDartType typeArgument, ResolutionDartType bound); |
| + DartType typeArgument, DartType bound); |
| /// Computes the [RuntimeTypesChecks] for the data in this builder. |
| - RuntimeTypesChecks computeRequiredChecks(); |
| + RuntimeTypesChecks computeRequiredChecks( |
| + CodegenWorldBuilder codegenWorldBuilder); |
| /// Compute type arguments of classes that use one of their type variables in |
| /// is-checks and add the is-checks that they imply. |
| /// |
| /// This function must be called after all is-checks have been registered. |
| void registerImplicitChecks( |
| - WorldBuilder worldBuilder, Iterable<ClassElement> classesUsingChecks); |
| + WorldBuilder worldBuilder, Iterable<ClassEntity> classesUsingChecks); |
| } |
| /// Interface for computing substitutions need for runtime type checks. |
| abstract class RuntimeTypesSubstitutions { |
| - bool isTrivialSubstitution(ClassElement cls, ClassElement check); |
| + bool isTrivialSubstitution(ClassEntity cls, ClassEntity check); |
| - Substitution getSubstitution(ClassElement cls, ClassElement other); |
| + Substitution getSubstitution(ClassEntity cls, ClassEntity other); |
| /// Compute the required type checks and substitutions for the given |
| /// instantitated and checked classes. |
| TypeChecks computeChecks( |
| - Set<ClassElement> instantiated, Set<ClassElement> checked); |
| + Set<ClassEntity> instantiated, Set<ClassEntity> checked); |
| - Set<ClassElement> getClassesUsedInSubstitutions(TypeChecks checks); |
| + Set<ClassEntity> getClassesUsedInSubstitutions(TypeChecks checks); |
| - static bool hasTypeArguments(ResolutionDartType type) { |
| - if (type is ResolutionInterfaceType) { |
| - ResolutionInterfaceType interfaceType = type; |
| + static bool hasTypeArguments(DartType type) { |
| + if (type is InterfaceType) { |
| + InterfaceType interfaceType = type; |
| return !interfaceType.treatAsRaw; |
| } |
| return false; |
| @@ -108,13 +127,13 @@ abstract class RuntimeTypesSubstitutions { |
| } |
| abstract class RuntimeTypesEncoder { |
| - bool isSimpleFunctionType(ResolutionFunctionType type); |
| + bool isSimpleFunctionType(FunctionType type); |
| jsAst.Expression getSignatureEncoding( |
| - Emitter emitter, ResolutionDartType type, jsAst.Expression this_); |
| + Emitter emitter, DartType type, jsAst.Expression this_); |
| - jsAst.Expression getSubstitutionRepresentation(Emitter emitter, |
| - List<ResolutionDartType> types, OnVariableCallback onVariable); |
| + jsAst.Expression getSubstitutionRepresentation( |
| + Emitter emitter, List<DartType> types, OnVariableCallback onVariable); |
| jsAst.Expression getSubstitutionCode( |
| Emitter emitter, Substitution substitution); |
| @@ -130,10 +149,10 @@ abstract class RuntimeTypesEncoder { |
| /// Returns a [jsAst.Expression] representing the given [type]. Type variables |
| /// are replaced by the [jsAst.Expression] returned by [onVariable]. |
| jsAst.Expression getTypeRepresentation( |
| - Emitter emitter, ResolutionDartType type, OnVariableCallback onVariable, |
| + Emitter emitter, DartType type, OnVariableCallback onVariable, |
| [ShouldEncodeTypedefCallback shouldEncodeTypedef]); |
| - String getTypeRepresentationForTypeConstant(ResolutionDartType type); |
| + String getTypeRepresentationForTypeConstant(DartType type); |
| } |
| /// Common functionality for [_RuntimeTypesNeedBuilder] and [_RuntimeTypes]. |
| @@ -236,12 +255,12 @@ class _RuntimeTypesNeed implements RuntimeTypesNeed { |
| return classesNeedingRti.contains(cls); |
| } |
| - bool methodNeedsRti(MethodElement function) { |
| + bool methodNeedsRti(FunctionEntity function) { |
| return methodsNeedingRti.contains(function) || |
| _backendUsage.isRuntimeTypeUsed; |
| } |
| - bool localFunctionNeedsRti(LocalFunctionElement function) { |
| + bool localFunctionNeedsRti(Local function) { |
| return localFunctionsNeedingRti.contains(function) || |
| _backendUsage.isRuntimeTypeUsed; |
| } |
| @@ -395,7 +414,7 @@ class RuntimeTypesNeedBuilderImpl extends _RuntimeTypesBase |
| // information. |
| resolutionWorldBuilder.isChecks.forEach((DartType type) { |
| if (type.isInterfaceType) { |
| - ResolutionInterfaceType itf = type; |
| + InterfaceType itf = type; |
| if (!itf.treatAsRaw) { |
| potentiallyAddForRti(itf.element); |
| } |
| @@ -474,15 +493,15 @@ class ResolutionRuntimeTypesNeedBuilderImpl |
| class _RuntimeTypesChecks implements RuntimeTypesChecks { |
| final RuntimeTypesSubstitutions substitutions; |
| final TypeChecks requiredChecks; |
| - final Set<ClassElement> directlyInstantiatedArguments; |
| - final Set<ClassElement> checkedArguments; |
| + final Set<ClassEntity> directlyInstantiatedArguments; |
| + final Set<ClassEntity> checkedArguments; |
| _RuntimeTypesChecks(this.substitutions, this.requiredChecks, |
| this.directlyInstantiatedArguments, this.checkedArguments); |
| @override |
| - Set<ClassElement> getRequiredArgumentClasses() { |
| - Set<ClassElement> requiredArgumentClasses = new Set<ClassElement>.from( |
| + Set<ClassEntity> getRequiredArgumentClasses() { |
| + Set<ClassEntity> requiredArgumentClasses = new Set<ClassEntity>.from( |
| substitutions.getClassesUsedInSubstitutions(requiredChecks)); |
| return requiredArgumentClasses |
| ..addAll(directlyInstantiatedArguments) |
| @@ -490,41 +509,35 @@ class _RuntimeTypesChecks implements RuntimeTypesChecks { |
| } |
| @override |
| - Set<ClassElement> getReferencedClasses(ResolutionFunctionType type) { |
| + Set<ClassEntity> getReferencedClasses(FunctionType type) { |
| FunctionArgumentCollector collector = new FunctionArgumentCollector(); |
| collector.collect(type); |
| return collector.classes; |
| } |
| } |
| -class _RuntimeTypes extends _RuntimeTypesBase |
| +class RuntimeTypesImpl extends _RuntimeTypesBase |
| implements RuntimeTypesChecksBuilder, RuntimeTypesSubstitutions { |
| - final Compiler compiler; |
| + final ElementEnvironment _elementEnvironment; |
| // The set of type arguments tested against type variable bounds. |
| - final Set<ResolutionDartType> checkedTypeArguments; |
| + final Set<DartType> checkedTypeArguments = new Set<DartType>(); |
| // The set of tested type variable bounds. |
| - final Set<ResolutionDartType> checkedBounds; |
| + final Set<DartType> checkedBounds = new Set<DartType>(); |
| TypeChecks cachedRequiredChecks; |
| - JavaScriptBackend get backend => compiler.backend; |
| - |
| bool rtiChecksBuilderClosed = false; |
| - _RuntimeTypes(Compiler compiler) |
| - : this.compiler = compiler, |
| - checkedTypeArguments = new Set<ResolutionDartType>(), |
| - checkedBounds = new Set<ResolutionDartType>(), |
| - super(compiler.types); |
| + RuntimeTypesImpl(this._elementEnvironment, DartTypes types) : super(types); |
| - Set<ClassElement> directlyInstantiatedArguments; |
| - Set<ClassElement> allInstantiatedArguments; |
| - Set<ClassElement> checkedArguments; |
| + Set<ClassEntity> directlyInstantiatedArguments; |
| + Set<ClassEntity> allInstantiatedArguments; |
| + Set<ClassEntity> checkedArguments; |
| @override |
| void registerTypeVariableBoundsSubtypeCheck( |
| - ResolutionDartType typeArgument, ResolutionDartType bound) { |
| + DartType typeArgument, DartType bound) { |
| checkedTypeArguments.add(typeArgument); |
| checkedBounds.add(bound); |
| } |
| @@ -536,16 +549,14 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| // arguments and record all combination where the element of a checked |
| // argument is a superclass of the element of an instantiated type. |
| TypeCheckMapping result = new TypeCheckMapping(); |
| - for (ClassElement element in instantiated) { |
| + for (ClassEntity element in instantiated) { |
| if (checked.contains(element)) { |
| result.add(element, element, null); |
| } |
| // Find all supertypes of [element] in [checkedArguments] and add checks |
| // and precompute the substitutions for them. |
| - assert(invariant(element, element.allSupertypes != null, |
| - message: 'Supertypes have not been computed for $element.')); |
| - for (ResolutionInterfaceType supertype in element.allSupertypes) { |
| - ClassElement superelement = supertype.element; |
| + for (InterfaceType supertype in _types.getSupertypes(element)) { |
| + ClassEntity superelement = supertype.element; |
| if (checked.contains(superelement)) { |
| Substitution substitution = |
| computeSubstitution(element, superelement); |
| @@ -556,11 +567,12 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| return result; |
| } |
| - RuntimeTypesChecks computeRequiredChecks() { |
| - Set<ResolutionDartType> isChecks = compiler.codegenWorldBuilder.isChecks; |
| + RuntimeTypesChecks computeRequiredChecks( |
| + CodegenWorldBuilder codegenWorldBuilder) { |
| + Set<DartType> isChecks = codegenWorldBuilder.isChecks; |
| // These types are needed for is-checks against function types. |
| - Set<ResolutionDartType> instantiatedTypesAndClosures = |
| - computeInstantiatedTypesAndClosures(compiler.codegenWorldBuilder); |
| + Set<DartType> instantiatedTypesAndClosures = |
| + computeInstantiatedTypesAndClosures(codegenWorldBuilder); |
| computeInstantiatedArguments(instantiatedTypesAndClosures, isChecks); |
| computeCheckedArguments(instantiatedTypesAndClosures, isChecks); |
| cachedRequiredChecks = |
| @@ -570,27 +582,24 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| directlyInstantiatedArguments, checkedArguments); |
| } |
| - Set<ResolutionDartType> computeInstantiatedTypesAndClosures( |
| - CodegenWorldBuilder worldBuilder) { |
| - Set<ResolutionDartType> instantiatedTypes = |
| - new Set<ResolutionDartType>.from(worldBuilder.instantiatedTypes); |
| - for (ResolutionInterfaceType instantiatedType |
| - in worldBuilder.instantiatedTypes) { |
| - ResolutionFunctionType callType = instantiatedType.callType; |
| + Set<DartType> computeInstantiatedTypesAndClosures( |
| + CodegenWorldBuilder codegenWorldBuilder) { |
| + Set<DartType> instantiatedTypes = |
| + new Set<DartType>.from(codegenWorldBuilder.instantiatedTypes); |
| + for (InterfaceType instantiatedType |
| + in codegenWorldBuilder.instantiatedTypes) { |
| + FunctionType callType = _types.getCallType(instantiatedType); |
| if (callType != null) { |
| instantiatedTypes.add(callType); |
| } |
| } |
| - for (FunctionElement element in worldBuilder.staticFunctionsNeedingGetter) { |
| - instantiatedTypes.add(element.type); |
| + for (FunctionEntity element |
| + in codegenWorldBuilder.staticFunctionsNeedingGetter) { |
| + instantiatedTypes.add(_elementEnvironment.getFunctionType(element)); |
| } |
| - // TODO(johnniwinther): We should get this information through the |
| - // [neededClasses] computed in the emitter instead of storing it and pulling |
| - // it from resolution, but currently it would introduce a cyclic dependency |
| - // between [computeRequiredChecks] and [computeNeededClasses]. |
| - for (MethodElement element |
| - in compiler.resolutionWorldBuilder.closurizedMembers) { |
| - instantiatedTypes.add(element.type); |
| + |
| + for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) { |
| + instantiatedTypes.add(_elementEnvironment.getFunctionType(element)); |
| } |
| return instantiatedTypes; |
| } |
| @@ -602,8 +611,8 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| * have a type check against this supertype that includes a check against |
| * the type arguments. |
| */ |
| - void computeInstantiatedArguments(Set<ResolutionDartType> instantiatedTypes, |
| - Set<ResolutionDartType> isChecks) { |
| + void computeInstantiatedArguments( |
| + Set<DartType> instantiatedTypes, Set<DartType> isChecks) { |
| ArgumentCollector superCollector = new ArgumentCollector(); |
| ArgumentCollector directCollector = new ArgumentCollector(); |
| FunctionArgumentCollector functionArgumentCollector = |
| @@ -611,8 +620,8 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| // We need to add classes occurring in function type arguments, like for |
| // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :]. |
| - void collectFunctionTypeArguments(Iterable<ResolutionDartType> types) { |
| - for (ResolutionDartType type in types) { |
| + void collectFunctionTypeArguments(Iterable<DartType> types) { |
| + for (DartType type in types) { |
| functionArgumentCollector.collect(type); |
| } |
| } |
| @@ -620,13 +629,13 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| collectFunctionTypeArguments(isChecks); |
| collectFunctionTypeArguments(checkedBounds); |
| - void collectTypeArguments(Iterable<ResolutionDartType> types, |
| + void collectTypeArguments(Iterable<DartType> types, |
| {bool isTypeArgument: false}) { |
| - for (ResolutionDartType type in types) { |
| + for (DartType type in types) { |
| directCollector.collect(type, isTypeArgument: isTypeArgument); |
| - if (type.isInterfaceType) { |
| - ClassElement cls = type.element; |
| - for (ResolutionInterfaceType supertype in cls.allSupertypes) { |
| + if (type is InterfaceType) { |
| + ClassEntity cls = type.element; |
| + for (InterfaceType supertype in _types.getSupertypes(cls)) { |
| superCollector.collect(supertype, isTypeArgument: isTypeArgument); |
| } |
| } |
| @@ -636,8 +645,8 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| collectTypeArguments(instantiatedTypes); |
| collectTypeArguments(checkedTypeArguments, isTypeArgument: true); |
| - for (ClassElement cls in superCollector.classes.toList()) { |
| - for (ResolutionInterfaceType supertype in cls.allSupertypes) { |
| + for (ClassEntity cls in superCollector.classes.toList()) { |
| + for (InterfaceType supertype in _types.getSupertypes(cls)) { |
| superCollector.collect(supertype); |
| } |
| } |
| @@ -649,8 +658,8 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| } |
| /// Collects all type arguments used in is-checks. |
| - void computeCheckedArguments(Set<ResolutionDartType> instantiatedTypes, |
| - Set<ResolutionDartType> isChecks) { |
| + void computeCheckedArguments( |
| + Set<DartType> instantiatedTypes, Set<DartType> isChecks) { |
| ArgumentCollector collector = new ArgumentCollector(); |
| FunctionArgumentCollector functionArgumentCollector = |
| new FunctionArgumentCollector(); |
| @@ -658,8 +667,8 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| // We need to add types occurring in function type arguments, like for |
| // instance 'J' for [: (J j) {} is f :] where f is |
| // [: typedef void f(I i); :] and 'J' is a subtype of 'I'. |
| - void collectFunctionTypeArguments(Iterable<ResolutionDartType> types) { |
| - for (ResolutionDartType type in types) { |
| + void collectFunctionTypeArguments(Iterable<DartType> types) { |
| + for (DartType type in types) { |
| functionArgumentCollector.collect(type); |
| } |
| } |
| @@ -667,9 +676,9 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| collectFunctionTypeArguments(instantiatedTypes); |
| collectFunctionTypeArguments(checkedTypeArguments); |
| - void collectTypeArguments(Iterable<ResolutionDartType> types, |
| + void collectTypeArguments(Iterable<DartType> types, |
| {bool isTypeArgument: false}) { |
| - for (ResolutionDartType type in types) { |
| + for (DartType type in types) { |
| collector.collect(type, isTypeArgument: isTypeArgument); |
| } |
| } |
| @@ -682,10 +691,10 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| } |
| @override |
| - Set<ClassElement> getClassesUsedInSubstitutions(TypeChecks checks) { |
| - Set<ClassElement> instantiated = new Set<ClassElement>(); |
| + Set<ClassEntity> getClassesUsedInSubstitutions(TypeChecks checks) { |
| + Set<ClassEntity> instantiated = new Set<ClassEntity>(); |
| ArgumentCollector collector = new ArgumentCollector(); |
| - for (ClassElement target in checks.classes) { |
| + for (ClassEntity target in checks.classes) { |
| instantiated.add(target); |
| for (TypeCheck check in checks[target]) { |
| Substitution substitution = check.substitution; |
| @@ -702,7 +711,7 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| // TODO(karlklose): maybe precompute this value and store it in typeChecks? |
| @override |
| - bool isTrivialSubstitution(ClassElement cls, ClassElement check) { |
| + bool isTrivialSubstitution(ClassEntity cls, ClassEntity check) { |
| if (cls.isClosure) { |
| // TODO(karlklose): handle closures. |
| return true; |
| @@ -710,12 +719,12 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| // If there are no type variables or the type is the same, we do not need |
| // a substitution. |
| - if (check.typeVariables.isEmpty || cls == check) { |
| + if (!_elementEnvironment.isGenericClass(check) || cls == check) { |
| return true; |
| } |
| - ResolutionInterfaceType originalType = cls.thisType; |
| - ResolutionInterfaceType type = originalType.asInstanceOf(check); |
| + InterfaceType originalType = _elementEnvironment.getThisType(cls); |
| + InterfaceType type = _types.asInstanceOf(originalType, check); |
| // [type] is not a subtype of [check]. we do not generate a check and do not |
| // need a substitution. |
| if (type == null) return true; |
| @@ -723,13 +732,13 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| // Run through both lists of type variables and check if the type variables |
| // are identical at each position. If they are not, we need to calculate a |
| // substitution function. |
| - List<ResolutionDartType> variables = cls.typeVariables; |
| - List<ResolutionDartType> arguments = type.typeArguments; |
| + List<DartType> variables = originalType.typeArguments; |
| + List<DartType> arguments = type.typeArguments; |
| if (variables.length != arguments.length) { |
| return false; |
| } |
| for (int index = 0; index < variables.length; index++) { |
| - if (variables[index].element != arguments[index].element) { |
| + if (variables[index] != arguments[index]) { |
| return false; |
| } |
| } |
| @@ -737,7 +746,7 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| } |
| @override |
| - Substitution getSubstitution(ClassElement cls, ClassElement other) { |
| + Substitution getSubstitution(ClassEntity cls, ClassEntity other) { |
| // Look for a precomputed check. |
| for (TypeCheck check in cachedRequiredChecks[cls]) { |
| if (check.cls == other) { |
| @@ -749,16 +758,16 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| return computeSubstitution(cls, other); |
| } |
| - Substitution computeSubstitution(ClassElement cls, ClassElement check, |
| + Substitution computeSubstitution(ClassEntity cls, ClassEntity check, |
| {bool alwaysGenerateFunction: false}) { |
| if (isTrivialSubstitution(cls, check)) return null; |
| // Unnamed mixin application classes do not need substitutions, because they |
| // are never instantiated and their checks are overwritten by the class that |
| // they are mixed into. |
| - ResolutionInterfaceType type = cls.thisType; |
| - ResolutionInterfaceType target = type.asInstanceOf(check); |
| - List<ResolutionDartType> typeVariables = cls.typeVariables; |
| + InterfaceType type = _elementEnvironment.getThisType(cls); |
| + InterfaceType target = _types.asInstanceOf(type, check); |
| + List<DartType> typeVariables = type.typeArguments; |
| if (typeVariables.isEmpty && !alwaysGenerateFunction) { |
| return new Substitution.list(target.typeArguments); |
| } else { |
| @@ -767,20 +776,22 @@ class _RuntimeTypes extends _RuntimeTypesBase |
| } |
| } |
| -class _RuntimeTypesEncoder implements RuntimeTypesEncoder { |
| +class RuntimeTypesEncoderImpl implements RuntimeTypesEncoder { |
| final Namer namer; |
| + final ElementEnvironment _elementEnvironment; |
| final CommonElements commonElements; |
| final TypeRepresentationGenerator _representationGenerator; |
| - _RuntimeTypesEncoder(this.namer, this.commonElements) |
| + RuntimeTypesEncoderImpl( |
| + this.namer, this._elementEnvironment, this.commonElements) |
| : _representationGenerator = new TypeRepresentationGenerator(namer); |
| @override |
| - bool isSimpleFunctionType(ResolutionFunctionType type) { |
| + bool isSimpleFunctionType(FunctionType type) { |
| if (!type.returnType.isDynamic) return false; |
| if (!type.optionalParameterTypes.isEmpty) return false; |
| if (!type.namedParameterTypes.isEmpty) return false; |
| - for (ResolutionDartType parameter in type.parameterTypes) { |
| + for (DartType parameter in type.parameterTypes) { |
| if (!parameter.isDynamic) return false; |
| } |
| return true; |
| @@ -802,29 +813,32 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder { |
| @override |
| jsAst.Expression getTypeRepresentation( |
| - Emitter emitter, ResolutionDartType type, OnVariableCallback onVariable, |
| + Emitter emitter, DartType type, OnVariableCallback onVariable, |
| [ShouldEncodeTypedefCallback shouldEncodeTypedef]) { |
| // GENERIC_METHODS: When generic method support is complete enough to |
| // include a runtime value for method type variables this must be updated. |
| - return _representationGenerator.getTypeRepresentation(emitter, |
| - type.dynamifyMethodTypeVariableType, onVariable, shouldEncodeTypedef); |
| + return _representationGenerator.getTypeRepresentation( |
| + emitter, |
| + type /*.dynamifyMethodTypeVariableType*/, |
|
Siggi Cherem (dart-lang)
2017/05/17 16:14:11
rewrite as TODO to make it easier to grep for?
Johnni Winther
2017/05/18 08:10:56
Should just have been removed. The dynamification
|
| + onVariable, |
| + shouldEncodeTypedef); |
| } |
| @override |
| - jsAst.Expression getSubstitutionRepresentation(Emitter emitter, |
| - List<ResolutionDartType> types, OnVariableCallback onVariable) { |
| + jsAst.Expression getSubstitutionRepresentation( |
| + Emitter emitter, List<DartType> types, OnVariableCallback onVariable) { |
| List<jsAst.Expression> elements = types |
| - .map((ResolutionDartType type) => |
| - getTypeRepresentation(emitter, type, onVariable)) |
| + .map( |
| + (DartType type) => getTypeRepresentation(emitter, type, onVariable)) |
| .toList(growable: false); |
| return new jsAst.ArrayInitializer(elements); |
| } |
| - jsAst.Expression getTypeEncoding(Emitter emitter, ResolutionDartType type, |
| + jsAst.Expression getTypeEncoding(Emitter emitter, DartType type, |
| {bool alwaysGenerateFunction: false}) { |
| - ClassElement contextClass = Types.getClassContext(type); |
| - jsAst.Expression onVariable(ResolutionTypeVariableType v) { |
| - return new jsAst.VariableUse(v.name); |
| + ClassEntity contextClass = Types.getClassContext(type); |
| + jsAst.Expression onVariable(TypeVariableType v) { |
| + return new jsAst.VariableUse(v.element.name); |
| } |
| jsAst.Expression encoding = |
| @@ -834,8 +848,11 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder { |
| } else { |
| List<String> parameters = const <String>[]; |
| if (contextClass != null) { |
| - parameters = contextClass.typeVariables.map((type) { |
| - return type.name; |
| + parameters = _elementEnvironment |
| + .getThisType(contextClass) |
| + .typeArguments |
| + .map((TypeVariableType type) { |
| + return type.element.name; |
| }).toList(); |
| } |
| return js('function(#) { return # }', [parameters, encoding]); |
| @@ -844,8 +861,8 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder { |
| @override |
| jsAst.Expression getSignatureEncoding( |
| - Emitter emitter, ResolutionDartType type, jsAst.Expression this_) { |
| - ClassElement contextClass = Types.getClassContext(type); |
| + Emitter emitter, DartType type, jsAst.Expression this_) { |
| + ClassEntity contextClass = Types.getClassContext(type); |
| jsAst.Expression encoding = |
| getTypeEncoding(emitter, type, alwaysGenerateFunction: true); |
| if (contextClass != null) { |
| @@ -878,23 +895,22 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder { |
| @override |
| jsAst.Expression getSubstitutionCode( |
| Emitter emitter, Substitution substitution) { |
| - jsAst.Expression declaration(ResolutionTypeVariableType variable) { |
| - return new jsAst.Parameter(getVariableName(variable.name)); |
| + jsAst.Expression declaration(TypeVariableType variable) { |
| + return new jsAst.Parameter(getVariableName(variable.element.name)); |
| } |
| - jsAst.Expression use(ResolutionTypeVariableType variable) { |
| - return new jsAst.VariableUse(getVariableName(variable.name)); |
| + jsAst.Expression use(TypeVariableType variable) { |
| + return new jsAst.VariableUse(getVariableName(variable.element.name)); |
| } |
| - if (substitution.arguments |
| - .every((ResolutionDartType type) => type.isDynamic)) { |
| + if (substitution.arguments.every((DartType type) => type.isDynamic)) { |
| return emitter.generateFunctionThatReturnsNull(); |
| } else { |
| jsAst.Expression value = |
| getSubstitutionRepresentation(emitter, substitution.arguments, use); |
| if (substitution.isFunction) { |
| Iterable<jsAst.Expression> formals = |
| - substitution.parameters.map(declaration); |
| + substitution.parameters.map((type) => declaration(type)); |
|
Siggi Cherem (dart-lang)
2017/05/17 16:14:11
undo?
Johnni Winther
2017/05/18 08:10:56
Can't do (stupid type system!): [declaration] has
|
| return js('function(#) { return # }', [formals, value]); |
| } else { |
| return js('function() { return # }', value); |
| @@ -911,19 +927,24 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder { |
| namer.internalGlobal('functionThatReturnsNull'); |
| @override |
| - String getTypeRepresentationForTypeConstant(ResolutionDartType type) { |
| + String getTypeRepresentationForTypeConstant(DartType type) { |
| if (type.isDynamic) return "dynamic"; |
| - String name = namer.uniqueNameForTypeConstantElement(type.element); |
| - if (!type.element.isClass) return name; |
| - ResolutionInterfaceType interface = type; |
| - List<ResolutionDartType> variables = interface.element.typeVariables; |
| + if (type is ResolutionTypedefType) { |
| + return namer.uniqueNameForTypeConstantElement( |
| + type.element.library, type.element); |
| + } |
| + InterfaceType interface = type; |
| + String name = namer.uniqueNameForTypeConstantElement( |
| + interface.element.library, interface.element); |
| + |
| // Type constants can currently only be raw types, so there is no point |
| // adding ground-term type parameters, as they would just be 'dynamic'. |
| // TODO(sra): Since the result string is used only in constructing constant |
| // names, it would result in more readable names if the final string was a |
| // legal JavaScript identifer. |
| - if (variables.isEmpty) return name; |
| - String arguments = new List.filled(variables.length, 'dynamic').join(', '); |
| + if (interface.typeArguments.isEmpty) return name; |
| + String arguments = |
| + new List.filled(interface.typeArguments.length, 'dynamic').join(', '); |
| return '$name<$arguments>'; |
| } |
| } |
| @@ -932,7 +953,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| final Namer namer; |
| OnVariableCallback onVariable; |
| ShouldEncodeTypedefCallback shouldEncodeTypedef; |
| - Map<ResolutionTypeVariableType, jsAst.Expression> typedefBindings; |
| + Map<TypeVariableType, jsAst.Expression> typedefBindings; |
| TypeRepresentationGenerator(this.namer); |
| @@ -942,7 +963,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| */ |
| jsAst.Expression getTypeRepresentation( |
| Emitter emitter, |
| - ResolutionDartType type, |
| + DartType type, |
| OnVariableCallback onVariable, |
| ShouldEncodeTypedefCallback encodeTypedef) { |
| assert(typedefBindings == null); |
| @@ -956,14 +977,22 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| return representation; |
| } |
| - jsAst.Expression getJavaScriptClassName(Element element, Emitter emitter) { |
| + jsAst.Expression getJavaScriptClassName(Entity element, Emitter emitter) { |
| return emitter.typeAccess(element); |
| } |
| - @override |
| - visit(ResolutionDartType type, Emitter emitter) => type.accept(this, emitter); |
| + jsAst.Expression getDynamicValue() => js('null'); |
| - visitTypeVariableType(ResolutionTypeVariableType type, Emitter emitter) { |
| + @override |
| + visit(DartType type, Emitter emitter) => type.accept(this, emitter); |
| + |
| + visitTypeVariableType(TypeVariableType type, Emitter emitter) { |
| + if (type.element.typeDeclaration is! ClassEntity) { |
| + /// A [TypeVariableType] from a generic method is replaced by a |
|
Siggi Cherem (dart-lang)
2017/05/17 16:14:11
this appears to be new - bug fix? should we add a
Johnni Winther
2017/05/18 08:10:56
This is instead of using [dynamifyMethodTypeVariab
|
| + /// [DynamicType]. |
| + /// GENERIC_METHODS: Temporary, only used with '--generic-method-syntax'. |
| + return getDynamicValue(); |
| + } |
| if (typedefBindings != null) { |
| assert(typedefBindings[type] != null); |
| return typedefBindings[type]; |
| @@ -971,24 +1000,24 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| return onVariable(type); |
| } |
| - visitDynamicType(ResolutionDynamicType type, Emitter emitter) { |
| - return js('null'); |
| + visitDynamicType(DynamicType type, Emitter emitter) { |
| + return getDynamicValue(); |
| } |
| - visitInterfaceType(ResolutionInterfaceType type, Emitter emitter) { |
| + visitInterfaceType(InterfaceType type, Emitter emitter) { |
| jsAst.Expression name = getJavaScriptClassName(type.element, emitter); |
| return type.treatAsRaw |
| ? name |
| : visitList(type.typeArguments, emitter, head: name); |
| } |
| - jsAst.Expression visitList(List<ResolutionDartType> types, Emitter emitter, |
| + jsAst.Expression visitList(List<DartType> types, Emitter emitter, |
| {jsAst.Expression head}) { |
| List<jsAst.Expression> elements = <jsAst.Expression>[]; |
| if (head != null) { |
| elements.add(head); |
| } |
| - for (ResolutionDartType type in types) { |
| + for (DartType type in types) { |
| jsAst.Expression element = visit(type, emitter); |
| if (element is jsAst.LiteralNull) { |
| elements.add(new jsAst.ArrayHole()); |
| @@ -1014,7 +1043,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| .expressionTemplateFor('{ ${namer.functionTypeTag}: "dynafunc" }'); |
| } |
| - visitFunctionType(ResolutionFunctionType type, Emitter emitter) { |
| + visitFunctionType(FunctionType type, Emitter emitter) { |
| List<jsAst.Property> properties = <jsAst.Property>[]; |
| void addProperty(String name, jsAst.Expression value) { |
| @@ -1041,7 +1070,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| if (!type.namedParameterTypes.isEmpty) { |
| List<jsAst.Property> namedArguments = <jsAst.Property>[]; |
| List<String> names = type.namedParameters; |
| - List<ResolutionDartType> types = type.namedParameterTypes; |
| + List<DartType> types = type.namedParameterTypes; |
| assert(types.length == names.length); |
| for (int index = 0; index < types.length; index++) { |
| jsAst.Expression name = js.string(names[index]); |
| @@ -1059,14 +1088,14 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| return js('null'); |
| } |
| - visitVoidType(ResolutionVoidType type, Emitter emitter) { |
| + visitVoidType(VoidType type, Emitter emitter) { |
| // TODO(ahe): Reify void type ("null" means "dynamic"). |
| return js('null'); |
| } |
| visitTypedefType(ResolutionTypedefType type, Emitter emitter) { |
| bool shouldEncode = shouldEncodeTypedef(type); |
| - ResolutionDartType unaliasedType = type.unaliased; |
| + DartType unaliasedType = type.unaliased; |
| var oldBindings = typedefBindings; |
| if (typedefBindings == null) { |
| @@ -1090,8 +1119,8 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| // HTypeInfoExpression). This would share all the Set<T> subexpressions |
| // instead of duplicating them. This would require HTypeInfoExpression |
| // inputs to correspond to type variables AND typedefs. |
| - typedefBindings = <ResolutionTypeVariableType, jsAst.Expression>{}; |
| - type.forEachTypeVariable((variable) { |
| + typedefBindings = <TypeVariableType, jsAst.Expression>{}; |
| + type.forEachTypeVariable((TypeVariableType variable) { |
| if (variable is! MethodTypeVariableType) { |
| typedefBindings[variable] = onVariable(variable); |
| } |
| @@ -1122,25 +1151,25 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor { |
| } |
| class TypeCheckMapping implements TypeChecks { |
| - final Map<ClassElement, Set<TypeCheck>> map = |
| - new Map<ClassElement, Set<TypeCheck>>(); |
| + final Map<ClassEntity, Set<TypeCheck>> map = |
| + new Map<ClassEntity, Set<TypeCheck>>(); |
| - Iterable<TypeCheck> operator [](ClassElement element) { |
| + Iterable<TypeCheck> operator [](ClassEntity element) { |
| Set<TypeCheck> result = map[element]; |
| return result != null ? result : const <TypeCheck>[]; |
| } |
| - void add(ClassElement cls, ClassElement check, Substitution substitution) { |
| + void add(ClassEntity cls, ClassEntity check, Substitution substitution) { |
| map.putIfAbsent(cls, () => new Set<TypeCheck>()); |
| map[cls].add(new TypeCheck(check, substitution)); |
| } |
| - Iterable<ClassElement> get classes => map.keys; |
| + Iterable<ClassEntity> get classes => map.keys; |
| String toString() { |
| StringBuffer sb = new StringBuffer(); |
| - for (ClassElement holder in classes) { |
| - for (ClassElement check in [holder]) { |
| + for (ClassEntity holder in classes) { |
| + for (ClassEntity check in [holder]) { |
| sb.write('${holder.name}.' '${check.name}, '); |
| } |
| } |
| @@ -1149,64 +1178,68 @@ class TypeCheckMapping implements TypeChecks { |
| } |
| class ArgumentCollector extends ResolutionDartTypeVisitor { |
| - final Set<ClassElement> classes = new Set<ClassElement>(); |
| + final Set<ClassEntity> classes = new Set<ClassEntity>(); |
| - collect(ResolutionDartType type, {bool isTypeArgument: false}) { |
| + collect(DartType type, {bool isTypeArgument: false}) { |
| visit(type, isTypeArgument); |
| } |
| /// Collect all types in the list as if they were arguments of an |
| /// InterfaceType. |
| - collectAll(List<ResolutionDartType> types) { |
| - for (ResolutionDartType type in types) { |
| + collectAll(List<DartType> types, {bool isTypeArgument: false}) { |
| + for (DartType type in types) { |
| visit(type, true); |
| } |
| } |
| visitTypedefType(ResolutionTypedefType type, bool isTypeArgument) { |
| - type.unaliased.accept(this, isTypeArgument); |
| + collect(type.unaliased, isTypeArgument: isTypeArgument); |
| } |
| - visitInterfaceType(ResolutionInterfaceType type, bool isTypeArgument) { |
| + visitInterfaceType(InterfaceType type, bool isTypeArgument) { |
| if (isTypeArgument) classes.add(type.element); |
| - type.visitChildren(this, true); |
| + collectAll(type.typeArguments, isTypeArgument: true); |
| } |
| - visitFunctionType(ResolutionFunctionType type, _) { |
| - type.visitChildren(this, true); |
| + visitFunctionType(FunctionType type, _) { |
| + collect(type.returnType, isTypeArgument: true); |
| + collectAll(type.parameterTypes, isTypeArgument: true); |
| + collectAll(type.optionalParameterTypes, isTypeArgument: true); |
| + collectAll(type.namedParameterTypes, isTypeArgument: true); |
| } |
| } |
| class FunctionArgumentCollector extends ResolutionDartTypeVisitor { |
| - final Set<ClassElement> classes = new Set<ClassElement>(); |
| + final Set<ClassEntity> classes = new Set<ClassEntity>(); |
| FunctionArgumentCollector(); |
| - collect(ResolutionDartType type) { |
| - visit(type, false); |
| + collect(DartType type, {bool inFunctionType: false}) { |
| + visit(type, inFunctionType); |
| } |
| - /// Collect all types in the list as if they were arguments of an |
| - /// InterfaceType. |
| - collectAll(Link<ResolutionDartType> types) { |
| - for (ResolutionDartType type in types) { |
| - visit(type, true); |
| + collectAll(List<DartType> types, {bool inFunctionType: false}) { |
| + for (DartType type in types) { |
| + visit(type, inFunctionType); |
| } |
| } |
| visitTypedefType(ResolutionTypedefType type, bool inFunctionType) { |
| - type.unaliased.accept(this, inFunctionType); |
| + collect(type.unaliased, inFunctionType: inFunctionType); |
| } |
| - visitInterfaceType(ResolutionInterfaceType type, bool inFunctionType) { |
| + visitInterfaceType(InterfaceType type, bool inFunctionType) { |
| if (inFunctionType) { |
| classes.add(type.element); |
| } |
| - type.visitChildren(this, inFunctionType); |
| + collectAll(type.typeArguments, inFunctionType: inFunctionType); |
| } |
| - visitFunctionType(ResolutionFunctionType type, _) { |
| - type.visitChildren(this, true); |
| + visitFunctionType(FunctionType type, _) { |
| + collect(type.returnType, inFunctionType: true); |
| + collectAll(type.parameterTypes, inFunctionType: true); |
| + collectAll(type.optionalParameterTypes, inFunctionType: true); |
| + collectAll(type.namedParameterTypes, inFunctionType: true); |
| } |
| } |
| @@ -1222,12 +1255,12 @@ class FunctionArgumentCollector extends ResolutionDartTypeVisitor { |
| //TODO(floitsch): Remove support for non-function substitutions. |
| class Substitution { |
| final bool isFunction; |
| - final List<ResolutionDartType> arguments; |
| - final List<ResolutionDartType> parameters; |
| + final List<DartType> arguments; |
| + final List<DartType> parameters; |
| Substitution.list(this.arguments) |
| : isFunction = false, |
| - parameters = const <ResolutionDartType>[]; |
| + parameters = const <DartType>[]; |
| Substitution.function(this.arguments, this.parameters) : isFunction = true; |
| } |
| @@ -1237,7 +1270,7 @@ class Substitution { |
| * substition for this check. |
| */ |
| class TypeCheck { |
| - final ClassElement cls; |
| + final ClassEntity cls; |
| final Substitution substitution; |
| final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30); |
| static int _nextHash = 0; |