Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: pkg/compiler/lib/src/kernel/element_map_impl.dart

Issue 3000763002: Implement .getCallType (Closed)
Patch Set: The fix Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart ('k') | pkg/compiler/lib/src/kernel/env.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698