Chromium Code Reviews| 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 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 ConstantValue computeConstantValue(ConstantExpression constant, | 456 ConstantValue computeConstantValue(ConstantExpression constant, |
| 457 {bool requireConstant: true}) { | 457 {bool requireConstant: true}) { |
| 458 return _constantEnvironment.getConstantValue(constant); | 458 return _constantEnvironment.getConstantValue(constant); |
| 459 } | 459 } |
| 460 | 460 |
| 461 DartType _substByContext(DartType type, InterfaceType context) { | 461 DartType _substByContext(DartType type, InterfaceType context) { |
| 462 return type.subst( | 462 return type.subst( |
| 463 context.typeArguments, _getThisType(context.element).typeArguments); | 463 context.typeArguments, _getThisType(context.element).typeArguments); |
| 464 } | 464 } |
| 465 | 465 |
| 466 void _ensureCallType(IndexedClass cls, ClassData data) { | |
| 467 if (!data.isCallTypeComputed) { | |
| 468 data.isCallTypeComputed = true; | |
| 469 MemberEntity callMethod = lookupClassMember(cls, Identifiers.call); | |
| 470 if (callMethod != null) { | |
| 471 if (callMethod.isFunction) { | |
| 472 data.callType = _getFunctionType(callMethod); | |
| 473 } else { | |
| 474 data.callType = const DynamicType(); | |
| 475 } | |
| 476 return; | |
| 477 } | |
| 478 | |
| 479 Set<FunctionType> inheritedCallTypes = new Set<FunctionType>(); | |
| 480 bool inheritsInvalidCallMember = false; | |
| 481 | |
| 482 void addCallType(InterfaceType supertype) { | |
| 483 if (supertype == null) return; | |
| 484 DartType type = _getCallType(supertype); | |
| 485 if (type == null) return; | |
| 486 if (type.isFunctionType) { | |
| 487 inheritedCallTypes.add(type); | |
| 488 } else { | |
| 489 inheritsInvalidCallMember = true; | |
| 490 } | |
| 491 } | |
| 492 | |
| 493 addCallType(_getSuperType(cls)); | |
| 494 _getInterfaces(cls).forEach(addCallType); | |
| 495 | |
| 496 if (inheritsInvalidCallMember) { | |
| 497 data.callType = const DynamicType(); | |
| 498 } else if (inheritedCallTypes.isEmpty) { | |
| 499 return; | |
| 500 } else if (inheritedCallTypes.length == 1) { | |
| 501 data.callType = inheritedCallTypes.single; | |
| 502 } else { | |
| 503 List<FunctionType> subtypesOfAllInherited = <FunctionType>[]; | |
|
Siggi Cherem (dart-lang)
2017/08/11 16:14:59
I am not sure it is worth it to replicate this log
Johnni Winther
2017/08/15 14:17:37
It's there. It works. And at some point Issue 3043
| |
| 504 outer: | |
| 505 for (FunctionType a in inheritedCallTypes) { | |
| 506 for (FunctionType b in inheritedCallTypes) { | |
| 507 if (identical(a, b)) continue; | |
| 508 if (!types.isSubtype(a, b)) continue outer; | |
|
Siggi Cherem (dart-lang)
2017/08/11 16:14:59
Assuming we still want to keep this logic, this pa
Johnni Winther
2017/08/15 14:17:37
For (int)->void and (num)->void both subtype the o
Siggi Cherem (dart-lang)
2017/08/15 18:10:27
but bivariance is not allowed in strong mode :)
F
| |
| 509 } | |
| 510 subtypesOfAllInherited.add(a); | |
| 511 } | |
| 512 if (subtypesOfAllInherited.length == 1) { | |
| 513 data.callType = subtypesOfAllInherited.single; | |
| 514 return; | |
| 515 } | |
| 516 | |
| 517 // Multiple signatures with different types => create the synthesized | |
| 518 // version. | |
|
Siggi Cherem (dart-lang)
2017/08/11 16:14:59
Here too - even if we keep the lookup for a glb an
Johnni Winther
2017/08/15 14:17:37
It is actually following the spec directly. Added
| |
| 519 int minRequiredParameters; | |
| 520 int maxPositionalParameters; | |
| 521 Set<String> names = new Set<String>(); | |
| 522 for (FunctionType type in inheritedCallTypes) { | |
| 523 type.namedParameters.forEach((String name) => names.add(name)); | |
| 524 int requiredParameters = type.parameterTypes.length; | |
| 525 int optionalParameters = type.optionalParameterTypes.length; | |
| 526 int positionalParameters = requiredParameters + optionalParameters; | |
| 527 if (minRequiredParameters == null || | |
| 528 minRequiredParameters > requiredParameters) { | |
| 529 minRequiredParameters = requiredParameters; | |
| 530 } | |
| 531 if (maxPositionalParameters == null || | |
| 532 maxPositionalParameters < positionalParameters) { | |
| 533 maxPositionalParameters = positionalParameters; | |
| 534 } | |
| 535 } | |
| 536 int optionalParameters = | |
| 537 maxPositionalParameters - minRequiredParameters; | |
| 538 // TODO(johnniwinther): Support function types with both optional | |
| 539 // and named parameters? | |
| 540 if (optionalParameters == 0 || names.isEmpty) { | |
| 541 DartType dynamic = const DynamicType(); | |
| 542 List<DartType> requiredParameterTypes = | |
| 543 new List.filled(minRequiredParameters, dynamic); | |
| 544 List<DartType> optionalParameterTypes = | |
| 545 new List.filled(optionalParameters, dynamic); | |
| 546 List<String> namedParameters = names.toList() | |
| 547 ..sort((a, b) => a.compareTo(b)); | |
| 548 List<DartType> namedParameterTypes = | |
| 549 new List.filled(namedParameters.length, dynamic); | |
| 550 data.callType = new FunctionType(dynamic, requiredParameterTypes, | |
| 551 optionalParameterTypes, namedParameters, namedParameterTypes); | |
| 552 } else { | |
| 553 // The function type is not valid. | |
| 554 data.callType = const DynamicType(); | |
| 555 } | |
| 556 } | |
| 557 } | |
| 558 } | |
| 559 | |
| 560 /// Returns the type of the `call` method on 'type'. | |
| 561 /// | |
| 562 /// If [type] doesn't have a `call` member `null` is returned. If [type] has | |
| 563 /// an invalid `call` member (non-method or a synthesized method with both | |
| 564 /// optional and named parameters) a [DynamicType] is returned. | |
| 565 DartType _getCallType(InterfaceType type) { | |
| 566 IndexedClass cls = type.element; | |
| 567 assert(checkFamily(cls)); | |
| 568 ClassData data = _classData[cls.classIndex]; | |
| 569 _ensureCallType(cls, data); | |
| 570 if (data.callType != null) { | |
| 571 return _substByContext(data.callType, type); | |
| 572 } | |
| 573 return null; | |
| 574 } | |
| 575 | |
| 466 InterfaceType _getThisType(IndexedClass cls) { | 576 InterfaceType _getThisType(IndexedClass cls) { |
| 467 assert(checkFamily(cls)); | 577 assert(checkFamily(cls)); |
| 468 ClassData data = _classData[cls.classIndex]; | 578 ClassData data = _classData[cls.classIndex]; |
| 469 _ensureThisAndRawType(cls, data); | 579 _ensureThisAndRawType(cls, data); |
| 470 return data.thisType; | 580 return data.thisType; |
| 471 } | 581 } |
| 472 | 582 |
| 473 InterfaceType _getRawType(IndexedClass cls) { | 583 InterfaceType _getRawType(IndexedClass cls) { |
| 474 assert(checkFamily(cls)); | 584 assert(checkFamily(cls)); |
| 475 ClassData data = _classData[cls.classIndex]; | 585 ClassData data = _classData[cls.classIndex]; |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1104 if (node is ir.FunctionDeclaration) { | 1214 if (node is ir.FunctionDeclaration) { |
| 1105 name = node.variable.name; | 1215 name = node.variable.name; |
| 1106 functionType = getFunctionType(node.function); | 1216 functionType = getFunctionType(node.function); |
| 1107 } else if (node is ir.FunctionExpression) { | 1217 } else if (node is ir.FunctionExpression) { |
| 1108 functionType = getFunctionType(node.function); | 1218 functionType = getFunctionType(node.function); |
| 1109 } | 1219 } |
| 1110 return new KLocalFunction( | 1220 return new KLocalFunction( |
| 1111 name, memberContext, executableContext, functionType); | 1221 name, memberContext, executableContext, functionType); |
| 1112 }); | 1222 }); |
| 1113 } | 1223 } |
| 1224 | |
| 1225 bool _implementsFunction(IndexedClass cls) { | |
| 1226 assert(checkFamily(cls)); | |
| 1227 ClassData data = _classData[cls.classIndex]; | |
| 1228 OrderedTypeSet orderedTypeSet = data.orderedTypeSet; | |
| 1229 InterfaceType supertype = orderedTypeSet.asInstanceOf( | |
| 1230 commonElements.functionClass, | |
| 1231 _getHierarchyDepth(commonElements.functionClass)); | |
| 1232 if (supertype != null) { | |
| 1233 return true; | |
| 1234 } | |
| 1235 _ensureCallType(cls, data); | |
| 1236 return data.callType is FunctionType; | |
| 1237 } | |
| 1114 } | 1238 } |
| 1115 | 1239 |
| 1116 class KernelElementEnvironment implements ElementEnvironment { | 1240 class KernelElementEnvironment implements ElementEnvironment { |
| 1117 final KernelToElementMapBase elementMap; | 1241 final KernelToElementMapBase elementMap; |
| 1118 | 1242 |
| 1119 KernelElementEnvironment(this.elementMap); | 1243 KernelElementEnvironment(this.elementMap); |
| 1120 | 1244 |
| 1121 @override | 1245 @override |
| 1122 DartType get dynamicType => const DynamicType(); | 1246 DartType get dynamicType => const DynamicType(); |
| 1123 | 1247 |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1534 return elementMap._getOrderedTypeSet(cls).supertypes; | 1658 return elementMap._getOrderedTypeSet(cls).supertypes; |
| 1535 } | 1659 } |
| 1536 | 1660 |
| 1537 @override | 1661 @override |
| 1538 ClassEntity getSuperClass(ClassEntity cls) { | 1662 ClassEntity getSuperClass(ClassEntity cls) { |
| 1539 return elementMap._getSuperType(cls)?.element; | 1663 return elementMap._getSuperType(cls)?.element; |
| 1540 } | 1664 } |
| 1541 | 1665 |
| 1542 @override | 1666 @override |
| 1543 bool implementsFunction(ClassEntity cls) { | 1667 bool implementsFunction(ClassEntity cls) { |
| 1544 // TODO(redemption): Implement this. | 1668 return elementMap._implementsFunction(cls); |
| 1545 return false; | |
| 1546 } | 1669 } |
| 1547 | 1670 |
| 1548 @override | 1671 @override |
| 1549 int getHierarchyDepth(ClassEntity cls) { | 1672 int getHierarchyDepth(ClassEntity cls) { |
| 1550 return elementMap._getHierarchyDepth(cls); | 1673 return elementMap._getHierarchyDepth(cls); |
| 1551 } | 1674 } |
| 1552 | 1675 |
| 1553 @override | 1676 @override |
| 1554 ClassEntity getAppliedMixin(ClassEntity cls) { | 1677 ClassEntity getAppliedMixin(ClassEntity cls) { |
| 1555 return elementMap._getAppliedMixin(cls); | 1678 return elementMap._getAppliedMixin(cls); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2157 /// | 2280 /// |
| 2158 /// These names are not used in generated code, just as element name. | 2281 /// These names are not used in generated code, just as element name. |
| 2159 String _getClosureVariableName(String name, int id) { | 2282 String _getClosureVariableName(String name, int id) { |
| 2160 return "_captured_${name}_$id"; | 2283 return "_captured_${name}_$id"; |
| 2161 } | 2284 } |
| 2162 | 2285 |
| 2163 String getDeferredUri(ir.LibraryDependency node) { | 2286 String getDeferredUri(ir.LibraryDependency node) { |
| 2164 throw new UnimplementedError('JsKernelToElementMap.getDeferredUri'); | 2287 throw new UnimplementedError('JsKernelToElementMap.getDeferredUri'); |
| 2165 } | 2288 } |
| 2166 } | 2289 } |
| OLD | NEW |