| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 library dart2js.kernel.element_map; | 5 library dart2js.kernel.element_map; |
| 6 | 6 |
| 7 import 'package:kernel/ast.dart' as ir; | 7 import 'package:kernel/ast.dart' as ir; |
| 8 | 8 |
| 9 import '../closure.dart' show BoxLocal; | 9 import '../closure.dart' show BoxLocal; |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 ConstantValue computeConstantValue(ConstantExpression constant, | 452 ConstantValue computeConstantValue(ConstantExpression constant, |
| 453 {bool requireConstant: true}) { | 453 {bool requireConstant: true}) { |
| 454 return _constantEnvironment.getConstantValue(constant); | 454 return _constantEnvironment.getConstantValue(constant); |
| 455 } | 455 } |
| 456 | 456 |
| 457 DartType _substByContext(DartType type, InterfaceType context) { | 457 DartType _substByContext(DartType type, InterfaceType context) { |
| 458 return type.subst( | 458 return type.subst( |
| 459 context.typeArguments, _getThisType(context.element).typeArguments); | 459 context.typeArguments, _getThisType(context.element).typeArguments); |
| 460 } | 460 } |
| 461 | 461 |
| 462 // TODO(johnniwinther): Remove this when call-type is provided by fasta. |
| 463 void _ensureCallType(IndexedClass cls, ClassData data) { |
| 464 if (!data.isCallTypeComputed) { |
| 465 data.isCallTypeComputed = true; |
| 466 MemberEntity callMethod = lookupClassMember(cls, Identifiers.call); |
| 467 if (callMethod != null) { |
| 468 if (callMethod.isFunction) { |
| 469 data.callType = _getFunctionType(callMethod); |
| 470 } else { |
| 471 data.callType = const DynamicType(); |
| 472 } |
| 473 return; |
| 474 } |
| 475 |
| 476 Set<FunctionType> inheritedCallTypes = new Set<FunctionType>(); |
| 477 bool inheritsInvalidCallMember = false; |
| 478 |
| 479 void addCallType(InterfaceType supertype) { |
| 480 if (supertype == null) return; |
| 481 DartType type = _getCallType(supertype); |
| 482 if (type == null) return; |
| 483 if (type.isFunctionType) { |
| 484 inheritedCallTypes.add(type); |
| 485 } else { |
| 486 inheritsInvalidCallMember = true; |
| 487 } |
| 488 } |
| 489 |
| 490 addCallType(_getSuperType(cls)); |
| 491 _getInterfaces(cls).forEach(addCallType); |
| 492 |
| 493 // Following §11.1.1 in the spec. |
| 494 if (inheritsInvalidCallMember) { |
| 495 // From §11.1.1 in the spec (continued): |
| 496 // |
| 497 // If some but not all of the m_i, 1 ≤ i ≤ k are getters none of the m_i |
| 498 // are inherited, and a static warning is issued. |
| 499 data.callType = const DynamicType(); |
| 500 } else if (inheritedCallTypes.isEmpty) { |
| 501 return; |
| 502 } else if (inheritedCallTypes.length == 1) { |
| 503 data.callType = inheritedCallTypes.single; |
| 504 } else { |
| 505 // From §11.1.1 in the spec (continued): |
| 506 // |
| 507 // Otherwise, if the static types T_1, ... , T_k of the members |
| 508 // m_1, ..., m_k are not identical, then there must be a member m_x such |
| 509 // that T_x <: T_i, 1 ≤ x ≤ k for all i ∈ 1..k, or a static type warning |
| 510 // occurs. |
| 511 List<FunctionType> subtypesOfAllInherited = <FunctionType>[]; |
| 512 outer: |
| 513 for (FunctionType a in inheritedCallTypes) { |
| 514 for (FunctionType b in inheritedCallTypes) { |
| 515 if (identical(a, b)) continue; |
| 516 if (!types.isSubtype(a, b)) continue outer; |
| 517 } |
| 518 subtypesOfAllInherited.add(a); |
| 519 } |
| 520 if (subtypesOfAllInherited.length == 1) { |
| 521 // From §11.1.1 in the spec (continued): |
| 522 // |
| 523 // The member that is inherited is m_x, if it exists. |
| 524 data.callType = subtypesOfAllInherited.single; |
| 525 return; |
| 526 } |
| 527 |
| 528 // From §11.1.1 in the spec (continued): |
| 529 // |
| 530 // Otherwise: let numberOfPositionals(f) denote the number of |
| 531 // positional parameters of a function f, and let |
| 532 // numberOfRequiredParams(f) denote the number of required parameters of |
| 533 // a function f. Furthermore, let s denote the set of all named |
| 534 // parameters of the m_1, . . . , m_k. Then let |
| 535 // |
| 536 // h = max(numberOfPositionals(mi)), |
| 537 // r = min(numberOfRequiredParams(mi)), i ∈ 1..k. |
| 538 |
| 539 // Then I has a method named n, with r required parameters of type |
| 540 // dynamic, h positional parameters of type dynamic, named parameters s |
| 541 // of type dynamic and return type dynamic. |
| 542 |
| 543 // Multiple signatures with different types => create the synthesized |
| 544 // version. |
| 545 int minRequiredParameters; |
| 546 int maxPositionalParameters; |
| 547 Set<String> names = new Set<String>(); |
| 548 for (FunctionType type in inheritedCallTypes) { |
| 549 type.namedParameters.forEach((String name) => names.add(name)); |
| 550 int requiredParameters = type.parameterTypes.length; |
| 551 int optionalParameters = type.optionalParameterTypes.length; |
| 552 int positionalParameters = requiredParameters + optionalParameters; |
| 553 if (minRequiredParameters == null || |
| 554 minRequiredParameters > requiredParameters) { |
| 555 minRequiredParameters = requiredParameters; |
| 556 } |
| 557 if (maxPositionalParameters == null || |
| 558 maxPositionalParameters < positionalParameters) { |
| 559 maxPositionalParameters = positionalParameters; |
| 560 } |
| 561 } |
| 562 int optionalParameters = |
| 563 maxPositionalParameters - minRequiredParameters; |
| 564 // TODO(johnniwinther): Support function types with both optional |
| 565 // and named parameters? |
| 566 if (optionalParameters == 0 || names.isEmpty) { |
| 567 DartType dynamic = const DynamicType(); |
| 568 List<DartType> requiredParameterTypes = |
| 569 new List.filled(minRequiredParameters, dynamic); |
| 570 List<DartType> optionalParameterTypes = |
| 571 new List.filled(optionalParameters, dynamic); |
| 572 List<String> namedParameters = names.toList() |
| 573 ..sort((a, b) => a.compareTo(b)); |
| 574 List<DartType> namedParameterTypes = |
| 575 new List.filled(namedParameters.length, dynamic); |
| 576 data.callType = new FunctionType(dynamic, requiredParameterTypes, |
| 577 optionalParameterTypes, namedParameters, namedParameterTypes); |
| 578 } else { |
| 579 // The function type is not valid. |
| 580 data.callType = const DynamicType(); |
| 581 } |
| 582 } |
| 583 } |
| 584 } |
| 585 |
| 586 /// Returns the type of the `call` method on 'type'. |
| 587 /// |
| 588 /// If [type] doesn't have a `call` member `null` is returned. If [type] has |
| 589 /// an invalid `call` member (non-method or a synthesized method with both |
| 590 /// optional and named parameters) a [DynamicType] is returned. |
| 591 DartType _getCallType(InterfaceType type) { |
| 592 IndexedClass cls = type.element; |
| 593 assert(checkFamily(cls)); |
| 594 ClassData data = _classData[cls.classIndex]; |
| 595 _ensureCallType(cls, data); |
| 596 if (data.callType != null) { |
| 597 return _substByContext(data.callType, type); |
| 598 } |
| 599 return null; |
| 600 } |
| 601 |
| 462 InterfaceType _getThisType(IndexedClass cls) { | 602 InterfaceType _getThisType(IndexedClass cls) { |
| 463 assert(checkFamily(cls)); | 603 assert(checkFamily(cls)); |
| 464 ClassData data = _classData[cls.classIndex]; | 604 ClassData data = _classData[cls.classIndex]; |
| 465 _ensureThisAndRawType(cls, data); | 605 _ensureThisAndRawType(cls, data); |
| 466 return data.thisType; | 606 return data.thisType; |
| 467 } | 607 } |
| 468 | 608 |
| 469 InterfaceType _getRawType(IndexedClass cls) { | 609 InterfaceType _getRawType(IndexedClass cls) { |
| 470 assert(checkFamily(cls)); | 610 assert(checkFamily(cls)); |
| 471 ClassData data = _classData[cls.classIndex]; | 611 ClassData data = _classData[cls.classIndex]; |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 if (node is ir.FunctionDeclaration) { | 1240 if (node is ir.FunctionDeclaration) { |
| 1101 name = node.variable.name; | 1241 name = node.variable.name; |
| 1102 functionType = getFunctionType(node.function); | 1242 functionType = getFunctionType(node.function); |
| 1103 } else if (node is ir.FunctionExpression) { | 1243 } else if (node is ir.FunctionExpression) { |
| 1104 functionType = getFunctionType(node.function); | 1244 functionType = getFunctionType(node.function); |
| 1105 } | 1245 } |
| 1106 return new KLocalFunction( | 1246 return new KLocalFunction( |
| 1107 name, memberContext, executableContext, functionType); | 1247 name, memberContext, executableContext, functionType); |
| 1108 }); | 1248 }); |
| 1109 } | 1249 } |
| 1250 |
| 1251 bool _implementsFunction(IndexedClass cls) { |
| 1252 assert(checkFamily(cls)); |
| 1253 ClassData data = _classData[cls.classIndex]; |
| 1254 OrderedTypeSet orderedTypeSet = data.orderedTypeSet; |
| 1255 InterfaceType supertype = orderedTypeSet.asInstanceOf( |
| 1256 commonElements.functionClass, |
| 1257 _getHierarchyDepth(commonElements.functionClass)); |
| 1258 if (supertype != null) { |
| 1259 return true; |
| 1260 } |
| 1261 _ensureCallType(cls, data); |
| 1262 return data.callType is FunctionType; |
| 1263 } |
| 1110 } | 1264 } |
| 1111 | 1265 |
| 1112 class KernelElementEnvironment implements ElementEnvironment { | 1266 class KernelElementEnvironment implements ElementEnvironment { |
| 1113 final KernelToElementMapBase elementMap; | 1267 final KernelToElementMapBase elementMap; |
| 1114 | 1268 |
| 1115 KernelElementEnvironment(this.elementMap); | 1269 KernelElementEnvironment(this.elementMap); |
| 1116 | 1270 |
| 1117 @override | 1271 @override |
| 1118 DartType get dynamicType => const DynamicType(); | 1272 DartType get dynamicType => const DynamicType(); |
| 1119 | 1273 |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 return elementMap._getOrderedTypeSet(cls).supertypes; | 1684 return elementMap._getOrderedTypeSet(cls).supertypes; |
| 1531 } | 1685 } |
| 1532 | 1686 |
| 1533 @override | 1687 @override |
| 1534 ClassEntity getSuperClass(ClassEntity cls) { | 1688 ClassEntity getSuperClass(ClassEntity cls) { |
| 1535 return elementMap._getSuperType(cls)?.element; | 1689 return elementMap._getSuperType(cls)?.element; |
| 1536 } | 1690 } |
| 1537 | 1691 |
| 1538 @override | 1692 @override |
| 1539 bool implementsFunction(ClassEntity cls) { | 1693 bool implementsFunction(ClassEntity cls) { |
| 1540 // TODO(redemption): Implement this. | 1694 return elementMap._implementsFunction(cls); |
| 1541 return false; | |
| 1542 } | 1695 } |
| 1543 | 1696 |
| 1544 @override | 1697 @override |
| 1545 int getHierarchyDepth(ClassEntity cls) { | 1698 int getHierarchyDepth(ClassEntity cls) { |
| 1546 return elementMap._getHierarchyDepth(cls); | 1699 return elementMap._getHierarchyDepth(cls); |
| 1547 } | 1700 } |
| 1548 | 1701 |
| 1549 @override | 1702 @override |
| 1550 ClassEntity getAppliedMixin(ClassEntity cls) { | 1703 ClassEntity getAppliedMixin(ClassEntity cls) { |
| 1551 return elementMap._getAppliedMixin(cls); | 1704 return elementMap._getAppliedMixin(cls); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2153 /// | 2306 /// |
| 2154 /// These names are not used in generated code, just as element name. | 2307 /// These names are not used in generated code, just as element name. |
| 2155 String _getClosureVariableName(String name, int id) { | 2308 String _getClosureVariableName(String name, int id) { |
| 2156 return "_captured_${name}_$id"; | 2309 return "_captured_${name}_$id"; |
| 2157 } | 2310 } |
| 2158 | 2311 |
| 2159 String getDeferredUri(ir.LibraryDependency node) { | 2312 String getDeferredUri(ir.LibraryDependency node) { |
| 2160 throw new UnimplementedError('JsKernelToElementMap.getDeferredUri'); | 2313 throw new UnimplementedError('JsKernelToElementMap.getDeferredUri'); |
| 2161 } | 2314 } |
| 2162 } | 2315 } |
| OLD | NEW |