| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /// For each class, stores the possible class subtype tests that could succeed. | 7 /// For each class, stores the possible class subtype tests that could succeed. |
| 8 abstract class TypeChecks { | 8 abstract class TypeChecks { |
| 9 /// Get the set of checks required for class [element]. | 9 /// Get the set of checks required for class [element]. |
| 10 Iterable<TypeCheck> operator[](ClassElement element); | 10 Iterable<TypeCheck> operator [](ClassElement element); |
| 11 |
| 11 /// Get the iterable for all classes that need type checks. | 12 /// Get the iterable for all classes that need type checks. |
| 12 Iterable<ClassElement> get classes; | 13 Iterable<ClassElement> get classes; |
| 13 } | 14 } |
| 14 | 15 |
| 15 typedef jsAst.Expression OnVariableCallback(TypeVariableType variable); | 16 typedef jsAst.Expression OnVariableCallback(TypeVariableType variable); |
| 16 typedef bool ShouldEncodeTypedefCallback(TypedefType variable); | 17 typedef bool ShouldEncodeTypedefCallback(TypedefType variable); |
| 17 | 18 |
| 18 // TODO(johnniwinther): Rename to something like [RuntimeTypeUsageCollector] | 19 // TODO(johnniwinther): Rename to something like [RuntimeTypeUsageCollector] |
| 19 // we semantics is more clear. | 20 // we semantics is more clear. |
| 20 abstract class RuntimeTypes { | 21 abstract class RuntimeTypes { |
| 21 TypeChecks get requiredChecks; | 22 TypeChecks get requiredChecks; |
| 22 Iterable<ClassElement> get classesNeedingRti; | 23 Iterable<ClassElement> get classesNeedingRti; |
| 23 Iterable<Element> get methodsNeedingRti; | 24 Iterable<Element> get methodsNeedingRti; |
| 24 | 25 |
| 25 /// The set of classes that use one of their type variables as expressions | 26 /// The set of classes that use one of their type variables as expressions |
| 26 /// to get the runtime type. | 27 /// to get the runtime type. |
| 27 Iterable<ClassElement> get classesUsingTypeVariableExpression; | 28 Iterable<ClassElement> get classesUsingTypeVariableExpression; |
| 28 | 29 |
| 29 void registerClassUsingTypeVariableExpression(ClassElement cls); | 30 void registerClassUsingTypeVariableExpression(ClassElement cls); |
| 30 void registerRtiDependency(Element element, Element dependency); | 31 void registerRtiDependency(Element element, Element dependency); |
| 31 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 32 void registerTypeVariableBoundsSubtypeCheck( |
| 32 DartType bound); | 33 DartType typeArgument, DartType bound); |
| 33 | 34 |
| 34 Set<ClassElement> getClassesUsedInSubstitutions(JavaScriptBackend backend, | 35 Set<ClassElement> getClassesUsedInSubstitutions( |
| 35 TypeChecks checks); | 36 JavaScriptBackend backend, TypeChecks checks); |
| 36 void computeClassesNeedingRti(); | 37 void computeClassesNeedingRti(); |
| 37 | 38 |
| 38 /// Compute the required type checkes and substitutions for the given | 39 /// Compute the required type checkes and substitutions for the given |
| 39 /// instantitated and checked classes. | 40 /// instantitated and checked classes. |
| 40 TypeChecks computeChecks(Set<ClassElement> instantiated, | 41 TypeChecks computeChecks( |
| 41 Set<ClassElement> checked); | 42 Set<ClassElement> instantiated, Set<ClassElement> checked); |
| 42 | 43 |
| 43 /// Compute type arguments of classes that use one of their type variables in | 44 /// Compute type arguments of classes that use one of their type variables in |
| 44 /// is-checks and add the is-checks that they imply. | 45 /// is-checks and add the is-checks that they imply. |
| 45 /// | 46 /// |
| 46 /// This function must be called after all is-checks have been registered. | 47 /// This function must be called after all is-checks have been registered. |
| 47 void addImplicitChecks(Universe universe, | 48 void addImplicitChecks( |
| 48 Iterable<ClassElement> classesUsingChecks); | 49 Universe universe, Iterable<ClassElement> classesUsingChecks); |
| 49 | 50 |
| 50 /// Return all classes that are referenced in the type of the function, i.e., | 51 /// Return all classes that are referenced in the type of the function, i.e., |
| 51 /// in the return type or the argument types. | 52 /// in the return type or the argument types. |
| 52 Set<ClassElement> getReferencedClasses(FunctionType type); | 53 Set<ClassElement> getReferencedClasses(FunctionType type); |
| 53 | 54 |
| 54 /// Return all classes that are uses a type arguments. | 55 /// Return all classes that are uses a type arguments. |
| 55 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend); | 56 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend); |
| 56 | 57 |
| 57 bool isTrivialSubstitution(ClassElement cls, ClassElement check); | 58 bool isTrivialSubstitution(ClassElement cls, ClassElement check); |
| 58 | 59 |
| 59 Substitution getSubstitution(ClassElement cls, ClassElement other); | 60 Substitution getSubstitution(ClassElement cls, ClassElement other); |
| 60 | 61 |
| 61 static bool hasTypeArguments(DartType type) { | 62 static bool hasTypeArguments(DartType type) { |
| 62 if (type is InterfaceType) { | 63 if (type is InterfaceType) { |
| 63 InterfaceType interfaceType = type; | 64 InterfaceType interfaceType = type; |
| 64 return !interfaceType.treatAsRaw; | 65 return !interfaceType.treatAsRaw; |
| 65 } | 66 } |
| 66 return false; | 67 return false; |
| 67 } | 68 } |
| 68 } | 69 } |
| 69 | 70 |
| 70 abstract class RuntimeTypesEncoder { | 71 abstract class RuntimeTypesEncoder { |
| 71 bool isSimpleFunctionType(FunctionType type); | 72 bool isSimpleFunctionType(FunctionType type); |
| 72 | 73 |
| 73 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_); | 74 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_); |
| 74 | 75 |
| 75 jsAst.Expression getSubstitutionRepresentation( | 76 jsAst.Expression getSubstitutionRepresentation( |
| 76 List<DartType> types, | 77 List<DartType> types, OnVariableCallback onVariable); |
| 77 OnVariableCallback onVariable); | |
| 78 jsAst.Expression getSubstitutionCode(Substitution substitution); | 78 jsAst.Expression getSubstitutionCode(Substitution substitution); |
| 79 jsAst.Expression getSubstitutionCodeForVariable( | 79 jsAst.Expression getSubstitutionCodeForVariable( |
| 80 Substitution substitution, int index); | 80 Substitution substitution, int index); |
| 81 | 81 |
| 82 /// Returns the JavaScript template to determine at runtime if a type object | 82 /// Returns the JavaScript template to determine at runtime if a type object |
| 83 /// is a function type. | 83 /// is a function type. |
| 84 jsAst.Template get templateForIsFunctionType; | 84 jsAst.Template get templateForIsFunctionType; |
| 85 | 85 |
| 86 /// Returns the JavaScript template that creates at runtime a new function | 86 /// Returns the JavaScript template that creates at runtime a new function |
| 87 /// type object. | 87 /// type object. |
| 88 jsAst.Template get templateForCreateFunctionType; | 88 jsAst.Template get templateForCreateFunctionType; |
| 89 jsAst.Name get getFunctionThatReturnsNullName; | 89 jsAst.Name get getFunctionThatReturnsNullName; |
| 90 | 90 |
| 91 jsAst.Expression getTypeRepresentation( | 91 jsAst.Expression getTypeRepresentation( |
| 92 DartType type, | 92 DartType type, OnVariableCallback onVariable, |
| 93 OnVariableCallback onVariable, | 93 [ShouldEncodeTypedefCallback shouldEncodeTypedef]); |
| 94 [ShouldEncodeTypedefCallback shouldEncodeTypedef]); | |
| 95 /** | 94 /** |
| 96 * Returns a [jsAst.Expression] representing the given [type]. Type | 95 * Returns a [jsAst.Expression] representing the given [type]. Type |
| 97 * variables are replaced by placeholders in the ast. | 96 * variables are replaced by placeholders in the ast. |
| 98 * | 97 * |
| 99 * [firstPlaceholderIndex] is the index to use for the first placeholder. | 98 * [firstPlaceholderIndex] is the index to use for the first placeholder. |
| 100 * This is useful if the returned [jsAst.Expression] is only part of a | 99 * This is useful if the returned [jsAst.Expression] is only part of a |
| 101 * larger template. By default, indexing starts with 0. | 100 * larger template. By default, indexing starts with 0. |
| 102 */ | 101 */ |
| 103 jsAst.Expression getTypeRepresentationWithPlaceholders(DartType type, | 102 jsAst.Expression getTypeRepresentationWithPlaceholders( |
| 104 OnVariableCallback onVariable, {int firstPlaceholderIndex : 0}); | 103 DartType type, OnVariableCallback onVariable, |
| 104 {int firstPlaceholderIndex: 0}); |
| 105 | 105 |
| 106 String getTypeRepresentationForTypeConstant(DartType type); | 106 String getTypeRepresentationForTypeConstant(DartType type); |
| 107 } | 107 } |
| 108 | 108 |
| 109 class _RuntimeTypes implements RuntimeTypes { | 109 class _RuntimeTypes implements RuntimeTypes { |
| 110 final Compiler compiler; | 110 final Compiler compiler; |
| 111 | 111 |
| 112 final Map<ClassElement, Set<ClassElement>> rtiDependencies; | 112 final Map<ClassElement, Set<ClassElement>> rtiDependencies; |
| 113 | 113 |
| 114 @override | 114 @override |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 @override | 150 @override |
| 151 void registerRtiDependency(Element element, Element dependency) { | 151 void registerRtiDependency(Element element, Element dependency) { |
| 152 // We're not dealing with typedef for now. | 152 // We're not dealing with typedef for now. |
| 153 if (!element.isClass || !dependency.isClass) return; | 153 if (!element.isClass || !dependency.isClass) return; |
| 154 Set<ClassElement> classes = | 154 Set<ClassElement> classes = |
| 155 rtiDependencies.putIfAbsent(element, () => new Set<ClassElement>()); | 155 rtiDependencies.putIfAbsent(element, () => new Set<ClassElement>()); |
| 156 classes.add(dependency); | 156 classes.add(dependency); |
| 157 } | 157 } |
| 158 | 158 |
| 159 @override | 159 @override |
| 160 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 160 void registerTypeVariableBoundsSubtypeCheck( |
| 161 DartType bound) { | 161 DartType typeArgument, DartType bound) { |
| 162 checkedTypeArguments.add(typeArgument); | 162 checkedTypeArguments.add(typeArgument); |
| 163 checkedBounds.add(bound); | 163 checkedBounds.add(bound); |
| 164 } | 164 } |
| 165 | 165 |
| 166 // TODO(21969): remove this and analyze instantiated types and factory calls | 166 // TODO(21969): remove this and analyze instantiated types and factory calls |
| 167 // instead to find out which types are instantiated, if finitely many, or if | 167 // instead to find out which types are instantiated, if finitely many, or if |
| 168 // we have to use the more imprecise generic algorithm. | 168 // we have to use the more imprecise generic algorithm. |
| 169 bool get cannotDetermineInstantiatedTypesPrecisely => true; | 169 bool get cannotDetermineInstantiatedTypesPrecisely => true; |
| 170 | 170 |
| 171 /** | 171 /** |
| 172 * Compute type arguments of classes that use one of their type variables in | 172 * Compute type arguments of classes that use one of their type variables in |
| 173 * is-checks and add the is-checks that they imply. | 173 * is-checks and add the is-checks that they imply. |
| 174 * | 174 * |
| 175 * This function must be called after all is-checks have been registered. | 175 * This function must be called after all is-checks have been registered. |
| 176 * | 176 * |
| 177 * TODO(karlklose): move these computations into a function producing an | 177 * TODO(karlklose): move these computations into a function producing an |
| 178 * immutable datastructure. | 178 * immutable datastructure. |
| 179 */ | 179 */ |
| 180 @override | 180 @override |
| 181 void addImplicitChecks(Universe universe, | 181 void addImplicitChecks( |
| 182 Iterable<ClassElement> classesUsingChecks) { | 182 Universe universe, Iterable<ClassElement> classesUsingChecks) { |
| 183 // If there are no classes that use their variables in checks, there is | 183 // If there are no classes that use their variables in checks, there is |
| 184 // nothing to do. | 184 // nothing to do. |
| 185 if (classesUsingChecks.isEmpty) return; | 185 if (classesUsingChecks.isEmpty) return; |
| 186 Set<DartType> instantiatedTypes = universe.instantiatedTypes; | 186 Set<DartType> instantiatedTypes = universe.instantiatedTypes; |
| 187 if (cannotDetermineInstantiatedTypesPrecisely) { | 187 if (cannotDetermineInstantiatedTypesPrecisely) { |
| 188 for (DartType type in instantiatedTypes) { | 188 for (DartType type in instantiatedTypes) { |
| 189 if (type.kind != TypeKind.INTERFACE) continue; | 189 if (type.kind != TypeKind.INTERFACE) continue; |
| 190 InterfaceType interface = type; | 190 InterfaceType interface = type; |
| 191 do { | 191 do { |
| 192 for (DartType argument in interface.typeArguments) { | 192 for (DartType argument in interface.typeArguments) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 if (type.isFunctionType) { | 286 if (type.isFunctionType) { |
| 287 void analyzeMethod(TypedElement method) { | 287 void analyzeMethod(TypedElement method) { |
| 288 DartType memberType = method.type; | 288 DartType memberType = method.type; |
| 289 ClassElement contextClass = Types.getClassContext(memberType); | 289 ClassElement contextClass = Types.getClassContext(memberType); |
| 290 if (contextClass != null && | 290 if (contextClass != null && |
| 291 compiler.types.isPotentialSubtype(memberType, type)) { | 291 compiler.types.isPotentialSubtype(memberType, type)) { |
| 292 potentiallyAddForRti(contextClass); | 292 potentiallyAddForRti(contextClass); |
| 293 methodsNeedingRti.add(method); | 293 methodsNeedingRti.add(method); |
| 294 } | 294 } |
| 295 } | 295 } |
| 296 compiler.resolverWorld.closuresWithFreeTypeVariables.forEach( | 296 compiler.resolverWorld.closuresWithFreeTypeVariables |
| 297 analyzeMethod); | 297 .forEach(analyzeMethod); |
| 298 compiler.resolverWorld.callMethodsWithFreeTypeVariables.forEach( | 298 compiler.resolverWorld.callMethodsWithFreeTypeVariables |
| 299 analyzeMethod); | 299 .forEach(analyzeMethod); |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 }); | 302 }); |
| 303 if (compiler.options.enableTypeAssertions) { | 303 if (compiler.options.enableTypeAssertions) { |
| 304 void analyzeMethod(TypedElement method) { | 304 void analyzeMethod(TypedElement method) { |
| 305 DartType memberType = method.type; | 305 DartType memberType = method.type; |
| 306 ClassElement contextClass = Types.getClassContext(memberType); | 306 ClassElement contextClass = Types.getClassContext(memberType); |
| 307 if (contextClass != null) { | 307 if (contextClass != null) { |
| 308 potentiallyAddForRti(contextClass); | 308 potentiallyAddForRti(contextClass); |
| 309 methodsNeedingRti.add(method); | 309 methodsNeedingRti.add(method); |
| 310 } | 310 } |
| 311 } | 311 } |
| 312 compiler.resolverWorld.closuresWithFreeTypeVariables.forEach( | 312 compiler.resolverWorld.closuresWithFreeTypeVariables |
| 313 analyzeMethod); | 313 .forEach(analyzeMethod); |
| 314 compiler.resolverWorld.callMethodsWithFreeTypeVariables.forEach( | 314 compiler.resolverWorld.callMethodsWithFreeTypeVariables |
| 315 analyzeMethod); | 315 .forEach(analyzeMethod); |
| 316 } | 316 } |
| 317 // Add the classes that need RTI because they use a type variable as | 317 // Add the classes that need RTI because they use a type variable as |
| 318 // expression. | 318 // expression. |
| 319 classesUsingTypeVariableExpression.forEach(potentiallyAddForRti); | 319 classesUsingTypeVariableExpression.forEach(potentiallyAddForRti); |
| 320 } | 320 } |
| 321 | 321 |
| 322 @override | 322 @override |
| 323 TypeChecks get requiredChecks { | 323 TypeChecks get requiredChecks { |
| 324 if (cachedRequiredChecks == null) { | 324 if (cachedRequiredChecks == null) { |
| 325 computeRequiredChecks(); | 325 computeRequiredChecks(); |
| 326 } | 326 } |
| 327 assert(cachedRequiredChecks != null); | 327 assert(cachedRequiredChecks != null); |
| 328 return cachedRequiredChecks; | 328 return cachedRequiredChecks; |
| 329 } | 329 } |
| 330 | 330 |
| 331 @override | 331 @override |
| 332 TypeChecks computeChecks(Set<ClassElement> instantiated, | 332 TypeChecks computeChecks( |
| 333 Set<ClassElement> checked) { | 333 Set<ClassElement> instantiated, Set<ClassElement> checked) { |
| 334 // Run through the combination of instantiated and checked | 334 // Run through the combination of instantiated and checked |
| 335 // arguments and record all combination where the element of a checked | 335 // arguments and record all combination where the element of a checked |
| 336 // argument is a superclass of the element of an instantiated type. | 336 // argument is a superclass of the element of an instantiated type. |
| 337 TypeCheckMapping result = new TypeCheckMapping(); | 337 TypeCheckMapping result = new TypeCheckMapping(); |
| 338 for (ClassElement element in instantiated) { | 338 for (ClassElement element in instantiated) { |
| 339 if (checked.contains(element)) { | 339 if (checked.contains(element)) { |
| 340 result.add(element, element, null); | 340 result.add(element, element, null); |
| 341 } | 341 } |
| 342 // Find all supertypes of [element] in [checkedArguments] and add checks | 342 // Find all supertypes of [element] in [checkedArguments] and add checks |
| 343 // and precompute the substitutions for them. | 343 // and precompute the substitutions for them. |
| 344 assert(invariant(element, element.allSupertypes != null, | 344 assert(invariant(element, element.allSupertypes != null, |
| 345 message: 'Supertypes have not been computed for $element.')); | 345 message: 'Supertypes have not been computed for $element.')); |
| 346 for (DartType supertype in element.allSupertypes) { | 346 for (DartType supertype in element.allSupertypes) { |
| 347 ClassElement superelement = supertype.element; | 347 ClassElement superelement = supertype.element; |
| 348 if (checked.contains(superelement)) { | 348 if (checked.contains(superelement)) { |
| 349 Substitution substitution = | 349 Substitution substitution = |
| 350 computeSubstitution(element, superelement); | 350 computeSubstitution(element, superelement); |
| 351 result.add(element, superelement, substitution); | 351 result.add(element, superelement, substitution); |
| 352 } | 352 } |
| 353 } | 353 } |
| 354 } | 354 } |
| 355 return result; | 355 return result; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 return instantiatedTypes; | 391 return instantiatedTypes; |
| 392 } | 392 } |
| 393 | 393 |
| 394 /** | 394 /** |
| 395 * Collects all types used in type arguments of instantiated types. | 395 * Collects all types used in type arguments of instantiated types. |
| 396 * | 396 * |
| 397 * This includes type arguments used in supertype relations, because we may | 397 * This includes type arguments used in supertype relations, because we may |
| 398 * have a type check against this supertype that includes a check against | 398 * have a type check against this supertype that includes a check against |
| 399 * the type arguments. | 399 * the type arguments. |
| 400 */ | 400 */ |
| 401 void computeInstantiatedArguments(Set<DartType> instantiatedTypes, | 401 void computeInstantiatedArguments( |
| 402 Set<DartType> isChecks) { | 402 Set<DartType> instantiatedTypes, Set<DartType> isChecks) { |
| 403 ArgumentCollector superCollector = new ArgumentCollector(backend); | 403 ArgumentCollector superCollector = new ArgumentCollector(backend); |
| 404 ArgumentCollector directCollector = new ArgumentCollector(backend); | 404 ArgumentCollector directCollector = new ArgumentCollector(backend); |
| 405 FunctionArgumentCollector functionArgumentCollector = | 405 FunctionArgumentCollector functionArgumentCollector = |
| 406 new FunctionArgumentCollector(backend); | 406 new FunctionArgumentCollector(backend); |
| 407 | 407 |
| 408 // We need to add classes occuring in function type arguments, like for | 408 // We need to add classes occuring in function type arguments, like for |
| 409 // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :]. | 409 // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :]. |
| 410 void collectFunctionTypeArguments(Iterable<DartType> types) { | 410 void collectFunctionTypeArguments(Iterable<DartType> types) { |
| 411 for (DartType type in types) { | 411 for (DartType type in types) { |
| 412 functionArgumentCollector.collect(type); | 412 functionArgumentCollector.collect(type); |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 collectFunctionTypeArguments(isChecks); | 415 collectFunctionTypeArguments(isChecks); |
| 416 collectFunctionTypeArguments(checkedBounds); | 416 collectFunctionTypeArguments(checkedBounds); |
| 417 | 417 |
| 418 void collectTypeArguments(Iterable<DartType> types, | 418 void collectTypeArguments(Iterable<DartType> types, |
| 419 {bool isTypeArgument: false}) { | 419 {bool isTypeArgument: false}) { |
| 420 for (DartType type in types) { | 420 for (DartType type in types) { |
| 421 directCollector.collect(type, isTypeArgument: isTypeArgument); | 421 directCollector.collect(type, isTypeArgument: isTypeArgument); |
| 422 if (type.isInterfaceType) { | 422 if (type.isInterfaceType) { |
| 423 ClassElement cls = type.element; | 423 ClassElement cls = type.element; |
| 424 for (DartType supertype in cls.allSupertypes) { | 424 for (DartType supertype in cls.allSupertypes) { |
| 425 superCollector.collect(supertype, isTypeArgument: isTypeArgument); | 425 superCollector.collect(supertype, isTypeArgument: isTypeArgument); |
| 426 } | 426 } |
| 427 } | 427 } |
| 428 } | 428 } |
| 429 } | 429 } |
| 430 collectTypeArguments(instantiatedTypes); | 430 collectTypeArguments(instantiatedTypes); |
| 431 collectTypeArguments(checkedTypeArguments, isTypeArgument: true); | 431 collectTypeArguments(checkedTypeArguments, isTypeArgument: true); |
| 432 | 432 |
| 433 for (ClassElement cls in superCollector.classes.toList()) { | 433 for (ClassElement cls in superCollector.classes.toList()) { |
| 434 for (DartType supertype in cls.allSupertypes) { | 434 for (DartType supertype in cls.allSupertypes) { |
| 435 superCollector.collect(supertype); | 435 superCollector.collect(supertype); |
| 436 } | 436 } |
| 437 } | 437 } |
| 438 | 438 |
| 439 directlyInstantiatedArguments = | 439 directlyInstantiatedArguments = directCollector.classes |
| 440 directCollector.classes..addAll(functionArgumentCollector.classes); | 440 ..addAll(functionArgumentCollector.classes); |
| 441 allInstantiatedArguments = | 441 allInstantiatedArguments = superCollector.classes |
| 442 superCollector.classes..addAll(directlyInstantiatedArguments); | 442 ..addAll(directlyInstantiatedArguments); |
| 443 } | 443 } |
| 444 | 444 |
| 445 /// Collects all type arguments used in is-checks. | 445 /// Collects all type arguments used in is-checks. |
| 446 void computeCheckedArguments(Set<DartType> instantiatedTypes, | 446 void computeCheckedArguments( |
| 447 Set<DartType> isChecks) { | 447 Set<DartType> instantiatedTypes, Set<DartType> isChecks) { |
| 448 ArgumentCollector collector = new ArgumentCollector(backend); | 448 ArgumentCollector collector = new ArgumentCollector(backend); |
| 449 FunctionArgumentCollector functionArgumentCollector = | 449 FunctionArgumentCollector functionArgumentCollector = |
| 450 new FunctionArgumentCollector(backend); | 450 new FunctionArgumentCollector(backend); |
| 451 | 451 |
| 452 // We need to add types occuring in function type arguments, like for | 452 // We need to add types occuring in function type arguments, like for |
| 453 // instance 'J' for [: (J j) {} is f :] where f is | 453 // instance 'J' for [: (J j) {} is f :] where f is |
| 454 // [: typedef void f(I i); :] and 'J' is a subtype of 'I'. | 454 // [: typedef void f(I i); :] and 'J' is a subtype of 'I'. |
| 455 void collectFunctionTypeArguments(Iterable<DartType> types) { | 455 void collectFunctionTypeArguments(Iterable<DartType> types) { |
| 456 for (DartType type in types) { | 456 for (DartType type in types) { |
| 457 functionArgumentCollector.collect(type); | 457 functionArgumentCollector.collect(type); |
| 458 } | 458 } |
| 459 } | 459 } |
| 460 collectFunctionTypeArguments(instantiatedTypes); | 460 collectFunctionTypeArguments(instantiatedTypes); |
| 461 collectFunctionTypeArguments(checkedTypeArguments); | 461 collectFunctionTypeArguments(checkedTypeArguments); |
| 462 | 462 |
| 463 void collectTypeArguments(Iterable<DartType> types, | 463 void collectTypeArguments(Iterable<DartType> types, |
| 464 {bool isTypeArgument: false}) { | 464 {bool isTypeArgument: false}) { |
| 465 for (DartType type in types) { | 465 for (DartType type in types) { |
| 466 collector.collect(type, isTypeArgument: isTypeArgument); | 466 collector.collect(type, isTypeArgument: isTypeArgument); |
| 467 } | 467 } |
| 468 } | 468 } |
| 469 collectTypeArguments(isChecks); | 469 collectTypeArguments(isChecks); |
| 470 collectTypeArguments(checkedBounds, isTypeArgument: true); | 470 collectTypeArguments(checkedBounds, isTypeArgument: true); |
| 471 | 471 |
| 472 checkedArguments = | 472 checkedArguments = collector.classes |
| 473 collector.classes..addAll(functionArgumentCollector.classes); | 473 ..addAll(functionArgumentCollector.classes); |
| 474 } | 474 } |
| 475 | 475 |
| 476 @override | 476 @override |
| 477 Set<ClassElement> getClassesUsedInSubstitutions(JavaScriptBackend backend, | 477 Set<ClassElement> getClassesUsedInSubstitutions( |
| 478 TypeChecks checks) { | 478 JavaScriptBackend backend, TypeChecks checks) { |
| 479 Set<ClassElement> instantiated = new Set<ClassElement>(); | 479 Set<ClassElement> instantiated = new Set<ClassElement>(); |
| 480 ArgumentCollector collector = new ArgumentCollector(backend); | 480 ArgumentCollector collector = new ArgumentCollector(backend); |
| 481 for (ClassElement target in checks.classes) { | 481 for (ClassElement target in checks.classes) { |
| 482 instantiated.add(target); | 482 instantiated.add(target); |
| 483 for (TypeCheck check in checks[target]) { | 483 for (TypeCheck check in checks[target]) { |
| 484 Substitution substitution = check.substitution; | 484 Substitution substitution = check.substitution; |
| 485 if (substitution != null) { | 485 if (substitution != null) { |
| 486 collector.collectAll(substitution.arguments); | 486 collector.collectAll(substitution.arguments); |
| 487 } | 487 } |
| 488 } | 488 } |
| 489 } | 489 } |
| 490 return instantiated..addAll(collector.classes); | 490 return instantiated..addAll(collector.classes); |
| 491 } | 491 } |
| 492 | 492 |
| 493 @override | 493 @override |
| 494 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend) { | 494 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend) { |
| 495 Set<ClassElement> requiredArgumentClasses = | 495 Set<ClassElement> requiredArgumentClasses = new Set<ClassElement>.from( |
| 496 new Set<ClassElement>.from( | 496 getClassesUsedInSubstitutions(backend, requiredChecks)); |
| 497 getClassesUsedInSubstitutions(backend, requiredChecks)); | |
| 498 return requiredArgumentClasses | 497 return requiredArgumentClasses |
| 499 ..addAll(directlyInstantiatedArguments) | 498 ..addAll(directlyInstantiatedArguments) |
| 500 ..addAll(checkedArguments); | 499 ..addAll(checkedArguments); |
| 501 } | 500 } |
| 502 | 501 |
| 503 @override | 502 @override |
| 504 Set<ClassElement> getReferencedClasses(FunctionType type) { | 503 Set<ClassElement> getReferencedClasses(FunctionType type) { |
| 505 FunctionArgumentCollector collector = | 504 FunctionArgumentCollector collector = |
| 506 new FunctionArgumentCollector(backend); | 505 new FunctionArgumentCollector(backend); |
| 507 collector.collect(type); | 506 collector.collect(type); |
| 508 return collector.classes; | 507 return collector.classes; |
| 509 } | 508 } |
| 510 | 509 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 if (check.cls == other) { | 550 if (check.cls == other) { |
| 552 return check.substitution; | 551 return check.substitution; |
| 553 } | 552 } |
| 554 } | 553 } |
| 555 // There is no precomputed check for this pair (because the check is not | 554 // There is no precomputed check for this pair (because the check is not |
| 556 // done on type arguments only. Compute a new substitution. | 555 // done on type arguments only. Compute a new substitution. |
| 557 return computeSubstitution(cls, other); | 556 return computeSubstitution(cls, other); |
| 558 } | 557 } |
| 559 | 558 |
| 560 Substitution computeSubstitution(ClassElement cls, ClassElement check, | 559 Substitution computeSubstitution(ClassElement cls, ClassElement check, |
| 561 { bool alwaysGenerateFunction: false }) { | 560 {bool alwaysGenerateFunction: false}) { |
| 562 if (isTrivialSubstitution(cls, check)) return null; | 561 if (isTrivialSubstitution(cls, check)) return null; |
| 563 | 562 |
| 564 // Unnamed mixin application classes do not need substitutions, because they | 563 // Unnamed mixin application classes do not need substitutions, because they |
| 565 // are never instantiated and their checks are overwritten by the class that | 564 // are never instantiated and their checks are overwritten by the class that |
| 566 // they are mixed into. | 565 // they are mixed into. |
| 567 InterfaceType type = cls.thisType; | 566 InterfaceType type = cls.thisType; |
| 568 InterfaceType target = type.asInstanceOf(check); | 567 InterfaceType target = type.asInstanceOf(check); |
| 569 List<DartType> typeVariables = cls.typeVariables; | 568 List<DartType> typeVariables = cls.typeVariables; |
| 570 if (typeVariables.isEmpty && !alwaysGenerateFunction) { | 569 if (typeVariables.isEmpty && !alwaysGenerateFunction) { |
| 571 return new Substitution.list(target.typeArguments); | 570 return new Substitution.list(target.typeArguments); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 595 | 594 |
| 596 /// Returns the JavaScript template that creates at runtime a new function | 595 /// Returns the JavaScript template that creates at runtime a new function |
| 597 /// type object. | 596 /// type object. |
| 598 @override | 597 @override |
| 599 jsAst.Template get templateForCreateFunctionType { | 598 jsAst.Template get templateForCreateFunctionType { |
| 600 return representationGenerator.templateForCreateFunctionType; | 599 return representationGenerator.templateForCreateFunctionType; |
| 601 } | 600 } |
| 602 | 601 |
| 603 @override | 602 @override |
| 604 jsAst.Expression getTypeRepresentation( | 603 jsAst.Expression getTypeRepresentation( |
| 605 DartType type, | 604 DartType type, OnVariableCallback onVariable, |
| 606 OnVariableCallback onVariable, | |
| 607 [ShouldEncodeTypedefCallback shouldEncodeTypedef]) { | 605 [ShouldEncodeTypedefCallback shouldEncodeTypedef]) { |
| 608 return representationGenerator.getTypeRepresentation( | 606 return representationGenerator.getTypeRepresentation( |
| 609 type, onVariable, shouldEncodeTypedef); | 607 type, onVariable, shouldEncodeTypedef); |
| 610 } | 608 } |
| 611 | 609 |
| 612 @override | 610 @override |
| 613 jsAst.Expression getTypeRepresentationWithPlaceholders(DartType type, | 611 jsAst.Expression getTypeRepresentationWithPlaceholders( |
| 614 OnVariableCallback onVariable, {int firstPlaceholderIndex : 0}) { | 612 DartType type, OnVariableCallback onVariable, |
| 613 {int firstPlaceholderIndex: 0}) { |
| 615 // Create a type representation. For type variables call the original | 614 // Create a type representation. For type variables call the original |
| 616 // callback for side effects and return a template placeholder. | 615 // callback for side effects and return a template placeholder. |
| 617 int positions = firstPlaceholderIndex; | 616 int positions = firstPlaceholderIndex; |
| 618 jsAst.Expression representation = getTypeRepresentation(type, (variable) { | 617 jsAst.Expression representation = getTypeRepresentation(type, (variable) { |
| 619 onVariable(variable); | 618 onVariable(variable); |
| 620 return new jsAst.InterpolatedExpression(positions++); | 619 return new jsAst.InterpolatedExpression(positions++); |
| 621 }); | 620 }); |
| 622 return representation; | 621 return representation; |
| 623 } | 622 } |
| 624 | 623 |
| 625 @override | 624 @override |
| 626 jsAst.Expression getSubstitutionRepresentation( | 625 jsAst.Expression getSubstitutionRepresentation( |
| 627 List<DartType> types, | 626 List<DartType> types, OnVariableCallback onVariable) { |
| 628 OnVariableCallback onVariable) { | |
| 629 List<jsAst.Expression> elements = types | 627 List<jsAst.Expression> elements = types |
| 630 .map((DartType type) => getTypeRepresentation(type, onVariable)) | 628 .map((DartType type) => getTypeRepresentation(type, onVariable)) |
| 631 .toList(growable: false); | 629 .toList(growable: false); |
| 632 return new jsAst.ArrayInitializer(elements); | 630 return new jsAst.ArrayInitializer(elements); |
| 633 } | 631 } |
| 634 | 632 |
| 635 jsAst.Expression getTypeEncoding(DartType type, | 633 jsAst.Expression getTypeEncoding(DartType type, |
| 636 {bool alwaysGenerateFunction: false}) { | 634 {bool alwaysGenerateFunction: false}) { |
| 637 ClassElement contextClass = Types.getClassContext(type); | 635 ClassElement contextClass = Types.getClassContext(type); |
| 638 jsAst.Expression onVariable(TypeVariableType v) { | 636 jsAst.Expression onVariable(TypeVariableType v) { |
| 639 return new jsAst.VariableUse(v.name); | 637 return new jsAst.VariableUse(v.name); |
| 640 }; | 638 } |
| 639 ; |
| 641 jsAst.Expression encoding = getTypeRepresentation(type, onVariable); | 640 jsAst.Expression encoding = getTypeRepresentation(type, onVariable); |
| 642 if (contextClass == null && !alwaysGenerateFunction) { | 641 if (contextClass == null && !alwaysGenerateFunction) { |
| 643 return encoding; | 642 return encoding; |
| 644 } else { | 643 } else { |
| 645 List<String> parameters = const <String>[]; | 644 List<String> parameters = const <String>[]; |
| 646 if (contextClass != null) { | 645 if (contextClass != null) { |
| 647 parameters = contextClass.typeVariables.map((type) { | 646 parameters = contextClass.typeVariables.map((type) { |
| 648 return type.toString(); | 647 return type.toString(); |
| 649 }).toList(); | 648 }).toList(); |
| 650 } | 649 } |
| 651 return js('function(#) { return # }', [parameters, encoding]); | 650 return js('function(#) { return # }', [parameters, encoding]); |
| 652 } | 651 } |
| 653 } | 652 } |
| 654 | 653 |
| 655 @override | 654 @override |
| 656 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_) { | 655 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_) { |
| 657 ClassElement contextClass = Types.getClassContext(type); | 656 ClassElement contextClass = Types.getClassContext(type); |
| 658 jsAst.Expression encoding = | 657 jsAst.Expression encoding = |
| 659 getTypeEncoding(type, alwaysGenerateFunction: true); | 658 getTypeEncoding(type, alwaysGenerateFunction: true); |
| 660 if (contextClass != null) { | 659 if (contextClass != null) { |
| 661 JavaScriptBackend backend = compiler.backend; | 660 JavaScriptBackend backend = compiler.backend; |
| 662 jsAst.Name contextName = backend.namer.className(contextClass); | 661 jsAst.Name contextName = backend.namer.className(contextClass); |
| 663 return js('function () { return #(#, #, #); }', | 662 return js('function () { return #(#, #, #); }', [ |
| 664 [ backend.emitter.staticFunctionAccess( | 663 backend.emitter.staticFunctionAccess(backend.helpers.computeSignature), |
| 665 backend.helpers.computeSignature), | 664 encoding, |
| 666 encoding, this_, js.quoteName(contextName) ]); | 665 this_, |
| 666 js.quoteName(contextName) |
| 667 ]); |
| 667 } else { | 668 } else { |
| 668 return encoding; | 669 return encoding; |
| 669 } | 670 } |
| 670 } | 671 } |
| 671 | 672 |
| 672 /** | 673 /** |
| 673 * Compute a JavaScript expression that describes the necessary substitution | 674 * Compute a JavaScript expression that describes the necessary substitution |
| 674 * for type arguments in a subtype test. | 675 * for type arguments in a subtype test. |
| 675 * | 676 * |
| 676 * The result can be: | 677 * The result can be: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 702 Iterable<jsAst.Expression> formals = | 703 Iterable<jsAst.Expression> formals = |
| 703 substitution.parameters.map(declaration); | 704 substitution.parameters.map(declaration); |
| 704 return js('function(#) { return # }', [formals, value]); | 705 return js('function(#) { return # }', [formals, value]); |
| 705 } else { | 706 } else { |
| 706 return js('function() { return # }', value); | 707 return js('function() { return # }', value); |
| 707 } | 708 } |
| 708 } | 709 } |
| 709 } | 710 } |
| 710 | 711 |
| 711 @override | 712 @override |
| 712 jsAst.Expression getSubstitutionCodeForVariable(Substitution substitution, | 713 jsAst.Expression getSubstitutionCodeForVariable( |
| 713 int index) { | 714 Substitution substitution, int index) { |
| 714 jsAst.Expression declaration(TypeVariableType variable) { | 715 jsAst.Expression declaration(TypeVariableType variable) { |
| 715 return new jsAst.Parameter(getVariableName(variable.name)); | 716 return new jsAst.Parameter(getVariableName(variable.name)); |
| 716 } | 717 } |
| 717 | 718 |
| 718 jsAst.Expression use(TypeVariableType variable) { | 719 jsAst.Expression use(TypeVariableType variable) { |
| 719 return new jsAst.VariableUse(getVariableName(variable.name)); | 720 return new jsAst.VariableUse(getVariableName(variable.name)); |
| 720 } | 721 } |
| 721 | 722 |
| 722 if (substitution.arguments[index].isDynamic) { | 723 if (substitution.arguments[index].isDynamic) { |
| 723 return backend.emitter.emitter.generateFunctionThatReturnsNull(); | 724 return backend.emitter.emitter.generateFunctionThatReturnsNull(); |
| 724 } else { | 725 } else { |
| 725 jsAst.Expression value = | 726 jsAst.Expression value = |
| 726 getTypeRepresentation(substitution.arguments[index], use); | 727 getTypeRepresentation(substitution.arguments[index], use); |
| 727 Iterable<jsAst.Expression> formals = | 728 Iterable<jsAst.Expression> formals = |
| 728 substitution.parameters.map(declaration); | 729 substitution.parameters.map(declaration); |
| 729 return js('function(#) { return # }', [formals, value]); | 730 return js('function(#) { return # }', [formals, value]); |
| 730 } | 731 } |
| 731 } | 732 } |
| 732 | 733 |
| 733 String getVariableName(String name) { | 734 String getVariableName(String name) { |
| 734 return backend.namer.safeVariableName(name); | 735 return backend.namer.safeVariableName(name); |
| 735 } | 736 } |
| 736 | 737 |
| 737 @override | 738 @override |
| 738 jsAst.Name get getFunctionThatReturnsNullName | 739 jsAst.Name get getFunctionThatReturnsNullName => |
| 739 => backend.namer.internalGlobal('functionThatReturnsNull'); | 740 backend.namer.internalGlobal('functionThatReturnsNull'); |
| 740 | 741 |
| 741 @override | 742 @override |
| 742 String getTypeRepresentationForTypeConstant(DartType type) { | 743 String getTypeRepresentationForTypeConstant(DartType type) { |
| 743 JavaScriptBackend backend = compiler.backend; | 744 JavaScriptBackend backend = compiler.backend; |
| 744 Namer namer = backend.namer; | 745 Namer namer = backend.namer; |
| 745 if (type.isDynamic) return "dynamic"; | 746 if (type.isDynamic) return "dynamic"; |
| 746 String name = namer.uniqueNameForTypeConstantElement(type.element); | 747 String name = namer.uniqueNameForTypeConstantElement(type.element); |
| 747 if (!type.element.isClass) return name; | 748 if (!type.element.isClass) return name; |
| 748 InterfaceType interface = type; | 749 InterfaceType interface = type; |
| 749 List<DartType> variables = interface.element.typeVariables; | 750 List<DartType> variables = interface.element.typeVariables; |
| 750 // Type constants can currently only be raw types, so there is no point | 751 // Type constants can currently only be raw types, so there is no point |
| 751 // adding ground-term type parameters, as they would just be 'dynamic'. | 752 // adding ground-term type parameters, as they would just be 'dynamic'. |
| 752 // TODO(sra): Since the result string is used only in constructing constant | 753 // TODO(sra): Since the result string is used only in constructing constant |
| 753 // names, it would result in more readable names if the final string was a | 754 // names, it would result in more readable names if the final string was a |
| 754 // legal JavaScript identifer. | 755 // legal JavaScript identifer. |
| 755 if (variables.isEmpty) return name; | 756 if (variables.isEmpty) return name; |
| 756 String arguments = | 757 String arguments = new List.filled(variables.length, 'dynamic').join(', '); |
| 757 new List.filled(variables.length, 'dynamic').join(', '); | |
| 758 return '$name<$arguments>'; | 758 return '$name<$arguments>'; |
| 759 } | 759 } |
| 760 | 760 |
| 761 @override | 761 @override |
| 762 bool isSimpleFunctionType(FunctionType type) { | 762 bool isSimpleFunctionType(FunctionType type) { |
| 763 if (!type.returnType.isDynamic) return false; | 763 if (!type.returnType.isDynamic) return false; |
| 764 if (!type.optionalParameterTypes.isEmpty) return false; | 764 if (!type.optionalParameterTypes.isEmpty) return false; |
| 765 if (!type.namedParameterTypes.isEmpty) return false; | 765 if (!type.namedParameterTypes.isEmpty) return false; |
| 766 for (DartType parameter in type.parameterTypes ) { | 766 for (DartType parameter in type.parameterTypes) { |
| 767 if (!parameter.isDynamic) return false; | 767 if (!parameter.isDynamic) return false; |
| 768 } | 768 } |
| 769 return true; | 769 return true; |
| 770 } | 770 } |
| 771 } | 771 } |
| 772 | 772 |
| 773 class TypeRepresentationGenerator implements DartTypeVisitor { | 773 class TypeRepresentationGenerator implements DartTypeVisitor { |
| 774 final Compiler compiler; | 774 final Compiler compiler; |
| 775 OnVariableCallback onVariable; | 775 OnVariableCallback onVariable; |
| 776 ShouldEncodeTypedefCallback shouldEncodeTypedef; | 776 ShouldEncodeTypedefCallback shouldEncodeTypedef; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 /// is a function type. | 838 /// is a function type. |
| 839 jsAst.Template get templateForIsFunctionType { | 839 jsAst.Template get templateForIsFunctionType { |
| 840 return jsAst.js.expressionTemplateFor("'${namer.functionTypeTag}' in #"); | 840 return jsAst.js.expressionTemplateFor("'${namer.functionTypeTag}' in #"); |
| 841 } | 841 } |
| 842 | 842 |
| 843 /// Returns the JavaScript template that creates at runtime a new function | 843 /// Returns the JavaScript template that creates at runtime a new function |
| 844 /// type object. | 844 /// type object. |
| 845 jsAst.Template get templateForCreateFunctionType { | 845 jsAst.Template get templateForCreateFunctionType { |
| 846 // The value of the functionTypeTag can be anything. We use "dynaFunc" for | 846 // The value of the functionTypeTag can be anything. We use "dynaFunc" for |
| 847 // easier debugging. | 847 // easier debugging. |
| 848 return jsAst.js.expressionTemplateFor( | 848 return jsAst.js |
| 849 '{ ${namer.functionTypeTag}: "dynafunc" }'); | 849 .expressionTemplateFor('{ ${namer.functionTypeTag}: "dynafunc" }'); |
| 850 } | 850 } |
| 851 | 851 |
| 852 visitFunctionType(FunctionType type, _) { | 852 visitFunctionType(FunctionType type, _) { |
| 853 List<jsAst.Property> properties = <jsAst.Property>[]; | 853 List<jsAst.Property> properties = <jsAst.Property>[]; |
| 854 | 854 |
| 855 void addProperty(String name, jsAst.Expression value) { | 855 void addProperty(String name, jsAst.Expression value) { |
| 856 properties.add(new jsAst.Property(js.string(name), value)); | 856 properties.add(new jsAst.Property(js.string(name), value)); |
| 857 } | 857 } |
| 858 | 858 |
| 859 // Type representations for functions have a property which is a tag marking | 859 // Type representations for functions have a property which is a tag marking |
| 860 // them as function types. The value is not used, so '1' is just a dummy. | 860 // them as function types. The value is not used, so '1' is just a dummy. |
| 861 addProperty(namer.functionTypeTag, js.number(1)); | 861 addProperty(namer.functionTypeTag, js.number(1)); |
| 862 if (type.returnType.isVoid) { | 862 if (type.returnType.isVoid) { |
| 863 addProperty(namer.functionTypeVoidReturnTag, js('true')); | 863 addProperty(namer.functionTypeVoidReturnTag, js('true')); |
| 864 } else if (!type.returnType.treatAsDynamic) { | 864 } else if (!type.returnType.treatAsDynamic) { |
| 865 addProperty(namer.functionTypeReturnTypeTag, visit(type.returnType)); | 865 addProperty(namer.functionTypeReturnTypeTag, visit(type.returnType)); |
| 866 } | 866 } |
| 867 if (!type.parameterTypes.isEmpty) { | 867 if (!type.parameterTypes.isEmpty) { |
| 868 addProperty(namer.functionTypeRequiredParametersTag, | 868 addProperty(namer.functionTypeRequiredParametersTag, |
| 869 visitList(type.parameterTypes)); | 869 visitList(type.parameterTypes)); |
| 870 } | 870 } |
| 871 if (!type.optionalParameterTypes.isEmpty) { | 871 if (!type.optionalParameterTypes.isEmpty) { |
| 872 addProperty(namer.functionTypeOptionalParametersTag, | 872 addProperty(namer.functionTypeOptionalParametersTag, |
| 873 visitList(type.optionalParameterTypes)); | 873 visitList(type.optionalParameterTypes)); |
| 874 } | 874 } |
| 875 if (!type.namedParameterTypes.isEmpty) { | 875 if (!type.namedParameterTypes.isEmpty) { |
| 876 List<jsAst.Property> namedArguments = <jsAst.Property>[]; | 876 List<jsAst.Property> namedArguments = <jsAst.Property>[]; |
| 877 List<String> names = type.namedParameters; | 877 List<String> names = type.namedParameters; |
| 878 List<DartType> types = type.namedParameterTypes; | 878 List<DartType> types = type.namedParameterTypes; |
| 879 assert(types.length == names.length); | 879 assert(types.length == names.length); |
| 880 for (int index = 0; index < types.length; index++) { | 880 for (int index = 0; index < types.length; index++) { |
| 881 jsAst.Expression name = js.string(names[index]); | 881 jsAst.Expression name = js.string(names[index]); |
| 882 namedArguments.add(new jsAst.Property(name, visit(types[index]))); | 882 namedArguments.add(new jsAst.Property(name, visit(types[index]))); |
| 883 } | 883 } |
| 884 addProperty(namer.functionTypeNamedParametersTag, | 884 addProperty(namer.functionTypeNamedParametersTag, |
| 885 new jsAst.ObjectInitializer(namedArguments)); | 885 new jsAst.ObjectInitializer(namedArguments)); |
| 886 } | 886 } |
| 887 return new jsAst.ObjectInitializer(properties); | 887 return new jsAst.ObjectInitializer(properties); |
| 888 } | 888 } |
| 889 | 889 |
| 890 visitMalformedType(MalformedType type, _) { | 890 visitMalformedType(MalformedType type, _) { |
| 891 // Treat malformed types as dynamic at runtime. | 891 // Treat malformed types as dynamic at runtime. |
| 892 return js('null'); | 892 return js('null'); |
| 893 } | 893 } |
| 894 | 894 |
| 895 visitVoidType(VoidType type, _) { | 895 visitVoidType(VoidType type, _) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 910 // Add it to the function-type object. | 910 // Add it to the function-type object. |
| 911 jsAst.LiteralString tag = js.string(namer.typedefTag); | 911 jsAst.LiteralString tag = js.string(namer.typedefTag); |
| 912 initializer.properties.add(new jsAst.Property(tag, encodedTypedef)); | 912 initializer.properties.add(new jsAst.Property(tag, encodedTypedef)); |
| 913 return initializer; | 913 return initializer; |
| 914 } else { | 914 } else { |
| 915 return unaliasedType.accept(this, null); | 915 return unaliasedType.accept(this, null); |
| 916 } | 916 } |
| 917 } | 917 } |
| 918 | 918 |
| 919 visitStatementType(StatementType type, _) { | 919 visitStatementType(StatementType type, _) { |
| 920 reporter.internalError(NO_LOCATION_SPANNABLE, | 920 reporter.internalError( |
| 921 'Unexpected type: $type (${type.kind}).'); | 921 NO_LOCATION_SPANNABLE, 'Unexpected type: $type (${type.kind}).'); |
| 922 } | 922 } |
| 923 } | 923 } |
| 924 | 924 |
| 925 | |
| 926 class TypeCheckMapping implements TypeChecks { | 925 class TypeCheckMapping implements TypeChecks { |
| 927 final Map<ClassElement, Set<TypeCheck>> map = | 926 final Map<ClassElement, Set<TypeCheck>> map = |
| 928 new Map<ClassElement, Set<TypeCheck>>(); | 927 new Map<ClassElement, Set<TypeCheck>>(); |
| 929 | 928 |
| 930 Iterable<TypeCheck> operator[](ClassElement element) { | 929 Iterable<TypeCheck> operator [](ClassElement element) { |
| 931 Set<TypeCheck> result = map[element]; | 930 Set<TypeCheck> result = map[element]; |
| 932 return result != null ? result : const <TypeCheck>[]; | 931 return result != null ? result : const <TypeCheck>[]; |
| 933 } | 932 } |
| 934 | 933 |
| 935 void add(ClassElement cls, ClassElement check, Substitution substitution) { | 934 void add(ClassElement cls, ClassElement check, Substitution substitution) { |
| 936 map.putIfAbsent(cls, () => new Set<TypeCheck>()); | 935 map.putIfAbsent(cls, () => new Set<TypeCheck>()); |
| 937 map[cls].add(new TypeCheck(check, substitution)); | 936 map[cls].add(new TypeCheck(check, substitution)); |
| 938 } | 937 } |
| 939 | 938 |
| 940 Iterable<ClassElement> get classes => map.keys; | 939 Iterable<ClassElement> get classes => map.keys; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1028 //TODO(floitsch): Remove support for non-function substitutions. | 1027 //TODO(floitsch): Remove support for non-function substitutions. |
| 1029 class Substitution { | 1028 class Substitution { |
| 1030 final bool isFunction; | 1029 final bool isFunction; |
| 1031 final List<DartType> arguments; | 1030 final List<DartType> arguments; |
| 1032 final List<DartType> parameters; | 1031 final List<DartType> parameters; |
| 1033 | 1032 |
| 1034 Substitution.list(this.arguments) | 1033 Substitution.list(this.arguments) |
| 1035 : isFunction = false, | 1034 : isFunction = false, |
| 1036 parameters = const <DartType>[]; | 1035 parameters = const <DartType>[]; |
| 1037 | 1036 |
| 1038 Substitution.function(this.arguments, this.parameters) | 1037 Substitution.function(this.arguments, this.parameters) : isFunction = true; |
| 1039 : isFunction = true; | |
| 1040 } | 1038 } |
| 1041 | 1039 |
| 1042 /** | 1040 /** |
| 1043 * A pair of a class that we need a check against and the type argument | 1041 * A pair of a class that we need a check against and the type argument |
| 1044 * substition for this check. | 1042 * substition for this check. |
| 1045 */ | 1043 */ |
| 1046 class TypeCheck { | 1044 class TypeCheck { |
| 1047 final ClassElement cls; | 1045 final ClassElement cls; |
| 1048 final Substitution substitution; | 1046 final Substitution substitution; |
| 1049 final int hashCode = (nextHash++) & 0x3fffffff; | 1047 final int hashCode = (nextHash++) & 0x3fffffff; |
| 1050 static int nextHash = 49; | 1048 static int nextHash = 49; |
| 1051 | 1049 |
| 1052 TypeCheck(this.cls, this.substitution); | 1050 TypeCheck(this.cls, this.substitution); |
| 1053 } | 1051 } |
| OLD | NEW |