| 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 | |
| 602 InterfaceType _getThisType(IndexedClass cls) { | 462 InterfaceType _getThisType(IndexedClass cls) { |
| 603 assert(checkFamily(cls)); | 463 assert(checkFamily(cls)); |
| 604 ClassData data = _classData[cls.classIndex]; | 464 ClassData data = _classData[cls.classIndex]; |
| 605 _ensureThisAndRawType(cls, data); | 465 _ensureThisAndRawType(cls, data); |
| 606 return data.thisType; | 466 return data.thisType; |
| 607 } | 467 } |
| 608 | 468 |
| 609 InterfaceType _getRawType(IndexedClass cls) { | 469 InterfaceType _getRawType(IndexedClass cls) { |
| 610 assert(checkFamily(cls)); | 470 assert(checkFamily(cls)); |
| 611 ClassData data = _classData[cls.classIndex]; | 471 ClassData data = _classData[cls.classIndex]; |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 if (node is ir.FunctionDeclaration) { | 1100 if (node is ir.FunctionDeclaration) { |
| 1241 name = node.variable.name; | 1101 name = node.variable.name; |
| 1242 functionType = getFunctionType(node.function); | 1102 functionType = getFunctionType(node.function); |
| 1243 } else if (node is ir.FunctionExpression) { | 1103 } else if (node is ir.FunctionExpression) { |
| 1244 functionType = getFunctionType(node.function); | 1104 functionType = getFunctionType(node.function); |
| 1245 } | 1105 } |
| 1246 return new KLocalFunction( | 1106 return new KLocalFunction( |
| 1247 name, memberContext, executableContext, functionType); | 1107 name, memberContext, executableContext, functionType); |
| 1248 }); | 1108 }); |
| 1249 } | 1109 } |
| 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 } | |
| 1264 } | 1110 } |
| 1265 | 1111 |
| 1266 class KernelElementEnvironment implements ElementEnvironment { | 1112 class KernelElementEnvironment implements ElementEnvironment { |
| 1267 final KernelToElementMapBase elementMap; | 1113 final KernelToElementMapBase elementMap; |
| 1268 | 1114 |
| 1269 KernelElementEnvironment(this.elementMap); | 1115 KernelElementEnvironment(this.elementMap); |
| 1270 | 1116 |
| 1271 @override | 1117 @override |
| 1272 DartType get dynamicType => const DynamicType(); | 1118 DartType get dynamicType => const DynamicType(); |
| 1273 | 1119 |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1684 return elementMap._getOrderedTypeSet(cls).supertypes; | 1530 return elementMap._getOrderedTypeSet(cls).supertypes; |
| 1685 } | 1531 } |
| 1686 | 1532 |
| 1687 @override | 1533 @override |
| 1688 ClassEntity getSuperClass(ClassEntity cls) { | 1534 ClassEntity getSuperClass(ClassEntity cls) { |
| 1689 return elementMap._getSuperType(cls)?.element; | 1535 return elementMap._getSuperType(cls)?.element; |
| 1690 } | 1536 } |
| 1691 | 1537 |
| 1692 @override | 1538 @override |
| 1693 bool implementsFunction(ClassEntity cls) { | 1539 bool implementsFunction(ClassEntity cls) { |
| 1694 return elementMap._implementsFunction(cls); | 1540 // TODO(redemption): Implement this. |
| 1541 return false; |
| 1695 } | 1542 } |
| 1696 | 1543 |
| 1697 @override | 1544 @override |
| 1698 int getHierarchyDepth(ClassEntity cls) { | 1545 int getHierarchyDepth(ClassEntity cls) { |
| 1699 return elementMap._getHierarchyDepth(cls); | 1546 return elementMap._getHierarchyDepth(cls); |
| 1700 } | 1547 } |
| 1701 | 1548 |
| 1702 @override | 1549 @override |
| 1703 ClassEntity getAppliedMixin(ClassEntity cls) { | 1550 ClassEntity getAppliedMixin(ClassEntity cls) { |
| 1704 return elementMap._getAppliedMixin(cls); | 1551 return elementMap._getAppliedMixin(cls); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2306 /// | 2153 /// |
| 2307 /// These names are not used in generated code, just as element name. | 2154 /// These names are not used in generated code, just as element name. |
| 2308 String _getClosureVariableName(String name, int id) { | 2155 String _getClosureVariableName(String name, int id) { |
| 2309 return "_captured_${name}_$id"; | 2156 return "_captured_${name}_$id"; |
| 2310 } | 2157 } |
| 2311 | 2158 |
| 2312 String getDeferredUri(ir.LibraryDependency node) { | 2159 String getDeferredUri(ir.LibraryDependency node) { |
| 2313 throw new UnimplementedError('JsKernelToElementMap.getDeferredUri'); | 2160 throw new UnimplementedError('JsKernelToElementMap.getDeferredUri'); |
| 2314 } | 2161 } |
| 2315 } | 2162 } |
| OLD | NEW |