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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_types.dart

Issue 52263003: Implement least upper bound. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 7 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 dart_types; 5 library dart_types;
6 6
7 import 'dart:math' show min;
8
7 import 'dart2jslib.dart' show Compiler, invariant, Script, Message; 9 import 'dart2jslib.dart' show Compiler, invariant, Script, Message;
8 import 'elements/modelx.dart' 10 import 'elements/modelx.dart'
9 show VoidElementX, LibraryElementX, BaseClassElementX; 11 show VoidElementX, LibraryElementX, BaseClassElementX;
10 import 'elements/elements.dart'; 12 import 'elements/elements.dart';
11 import 'util/util.dart' show Link, LinkBuilder; 13 import 'ordered_typeset.dart' show OrderedTypeSet;
14 import 'util/util.dart' show Link, LinkBuilder, CURRENT_ELEMENT_SPANNABLE;
12 15
13 class TypeKind { 16 class TypeKind {
14 final String id; 17 final String id;
15 18
16 const TypeKind(String this.id); 19 const TypeKind(String this.id);
17 20
18 static const TypeKind FUNCTION = const TypeKind('function'); 21 static const TypeKind FUNCTION = const TypeKind('function');
19 static const TypeKind INTERFACE = const TypeKind('interface'); 22 static const TypeKind INTERFACE = const TypeKind('interface');
20 static const TypeKind STATEMENT = const TypeKind('statement'); 23 static const TypeKind STATEMENT = const TypeKind('statement');
21 static const TypeKind TYPEDEF = const TypeKind('typedef'); 24 static const TypeKind TYPEDEF = const TypeKind('typedef');
(...skipping 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after
1470 } else if (!b.isEmpty) { 1473 } else if (!b.isEmpty) {
1471 // [b] is longer than [a] => a < b. 1474 // [b] is longer than [a] => a < b.
1472 return -1; 1475 return -1;
1473 } 1476 }
1474 return 0; 1477 return 0;
1475 } 1478 }
1476 1479
1477 static List<DartType> sorted(Iterable<DartType> types) { 1480 static List<DartType> sorted(Iterable<DartType> types) {
1478 return types.toList()..sort(compare); 1481 return types.toList()..sort(compare);
1479 } 1482 }
1483
1484 /// Computes the least upper bound of two interface types [a] and [b].
1485 InterfaceType computeLeastUpperBoundInterfaces(InterfaceType a,
1486 InterfaceType b) {
1487
1488 /// Returns the set of supertypes of [type] at depth [depth].
1489 Set<DartType> getSupertypesAtDepth(InterfaceType type, int depth) {
1490 ClassElement cls = type.element;
1491 OrderedTypeSet types = cls.allSupertypesAndSelf;
1492 Link<DartType> typeVariables = cls.typeVariables;
1493 Link<DartType> typeArguments = type.typeArguments;
1494 Set<DartType> set = new Set<DartType>();
1495 types.forEach(depth, (DartType type) {
1496 set.add(type.subst(typeArguments, typeVariables));
1497 });
1498 return set;
1499 }
1500
1501 ClassElement aClass = a.element;
1502 ClassElement bClass = b.element;
1503 int maxCommonDepth = min(aClass.hierarchyDepth, bClass.hierarchyDepth);
1504 for (int depth = maxCommonDepth; depth >= 0; depth--) {
1505 Set<DartType> aTypeSet = getSupertypesAtDepth(a, depth);
1506 Set<DartType> bTypeSet = getSupertypesAtDepth(b, depth);
1507 Set<DartType> intersection = aTypeSet..retainAll(bTypeSet);
1508 if (intersection.length == 1) {
1509 return intersection.first;
1510 }
1511 }
1512 assert(invariant(CURRENT_ELEMENT_SPANNABLE, false,
1513 message: 'No least upper bound computed for $a and $b.'));
1514 }
1515
1516 /// Computes the least upper bound of the types in the longest prefix of [a]
1517 /// and [b].
1518 Link<DartType> computeLeastUpperBoundsTypes(Link<DartType> a,
1519 Link<DartType> b) {
1520 if (a.isEmpty || b.isEmpty) return const Link<DartType>();
1521 LinkBuilder<DartType> types = new LinkBuilder<DartType>();
1522 while (!a.isEmpty && !b.isEmpty) {
1523 types.addLast(computeLeastUpperBound(a.head, b.head));
1524 a = a.tail;
1525 b = b.tail;
1526 }
1527 return types.toLink();
1528 }
1529
1530 /// Computes the least upper bound of two function types [a] and [b].
1531 ///
1532 /// If the required parameter count of [a] and [b] does not match, `Function`
1533 /// is returned.
1534 ///
1535 /// Otherwise, a function type is returned whose return type and
1536 /// parameter types are the least upper bound of those of [a] and [b],
1537 /// respectively. In addition, the optional parameters are the least upper
1538 /// bound of the longest common prefix of the optional parameters of [a] and
1539 /// [b], and the named parameters are the least upper bound of those common to
1540 /// [a] and [b].
1541 DartType computeLeastUpperBoundFunctionTypes(FunctionType a,
1542 FunctionType b) {
1543 if (a.parameterTypes.slowLength() != b.parameterTypes.slowLength()) {
1544 return compiler.functionClass.rawType;
1545 }
1546 DartType returnType = computeLeastUpperBound(a.returnType, b.returnType);
1547 Link<DartType> parameterTypes =
1548 computeLeastUpperBoundsTypes(a.parameterTypes, b.parameterTypes);
1549 Link<DartType> optionalParameterTypes =
1550 computeLeastUpperBoundsTypes(a.optionalParameterTypes,
1551 b.optionalParameterTypes);
1552 LinkBuilder<String> namedParameters = new LinkBuilder<String>();
1553 Link<String> aNamedParameters = a.namedParameters;
1554 Link<String> bNamedParameters = b.namedParameters;
1555 LinkBuilder<DartType> namedParameterTypes = new LinkBuilder<DartType>();
1556 Link<DartType> aNamedParameterTypes = a.namedParameterTypes;
1557 Link<DartType> bNamedParameterTypes = b.namedParameterTypes;
1558 while (!aNamedParameters.isEmpty && !bNamedParameters.isEmpty) {
1559 String aNamedParameter = aNamedParameters.head;
1560 String bNamedParameter = bNamedParameters.head;
1561 int result = aNamedParameter.compareTo(bNamedParameter);
1562 if (result == 0) {
1563 namedParameters.addLast(aNamedParameter);
1564 namedParameterTypes.addLast(computeLeastUpperBound(
1565 aNamedParameterTypes.head, bNamedParameterTypes.head));
1566 }
1567 if (result <= 0) {
1568 aNamedParameters = aNamedParameters.tail;
1569 aNamedParameterTypes = aNamedParameterTypes.tail;
1570 }
1571 if (result >= 0) {
1572 bNamedParameters = bNamedParameters.tail;
1573 bNamedParameterTypes = bNamedParameterTypes.tail;
1574 }
1575 }
1576 return new FunctionType(compiler.functionClass,
1577 returnType,
1578 parameterTypes, optionalParameterTypes,
1579 namedParameters.toLink(), namedParameterTypes.toLink());
1580 }
1581
1582 /// Computes the least upper bound of two types of which at least one is a
1583 /// type variable. The least upper bound of a type variable is defined in
1584 /// terms of its bound, but to ensure reflexivity we need to check for common
1585 /// bounds transitively.
1586 DartType computeLeastUpperBoundTypeVariableTypes(DartType a,
1587 DartType b) {
1588 Set<DartType> typeVariableBounds = new Set<DartType>();
1589 while (a.kind == TypeKind.TYPE_VARIABLE) {
1590 if (a == b) return a;
1591 typeVariableBounds.add(a);
1592 TypeVariableElement element = a.element;
1593 a = element.bound;
1594 }
1595 while (b.kind == TypeKind.TYPE_VARIABLE) {
1596 if (typeVariableBounds.contains(b)) return b;
1597 TypeVariableElement element = b.element;
1598 b = element.bound;
1599 }
1600 return computeLeastUpperBound(a, b);
1601 }
1602
1603 /// Computes the least upper bound for [a] and [b].
1604 DartType computeLeastUpperBound(DartType a, DartType b) {
1605 if (a == b) return a;
1606
1607 if (a.kind == TypeKind.TYPE_VARIABLE ||
1608 b.kind == TypeKind.TYPE_VARIABLE) {
1609 return computeLeastUpperBoundTypeVariableTypes(a, b);
1610 }
1611
1612 a = a.unalias(compiler);
1613 b = b.unalias(compiler);
1614
1615 if (a.treatAsDynamic || b.treatAsDynamic) return dynamicType;
1616 if (a.isVoid || b.isVoid) return voidType;
1617
1618 if (a.kind == TypeKind.FUNCTION && b.kind == TypeKind.FUNCTION) {
1619 return computeLeastUpperBoundFunctionTypes(a, b);
1620 }
1621
1622 if (a.kind == TypeKind.FUNCTION) {
1623 a = compiler.functionClass.rawType;
1624 }
1625 if (b.kind == TypeKind.FUNCTION) {
1626 b = compiler.functionClass.rawType;
1627 }
1628
1629 if (a.kind == TypeKind.INTERFACE && b.kind == TypeKind.INTERFACE) {
1630 return computeLeastUpperBoundInterfaces(a, b);
1631 }
1632 return dynamicType;
1633 }
1480 } 1634 }
1481 1635
1482 /** 1636 /**
1483 * Type visitor that determines one type could a subtype of another given the 1637 * Type visitor that determines one type could a subtype of another given the
1484 * right type variable substitution. The computation is approximate and returns 1638 * right type variable substitution. The computation is approximate and returns
1485 * [:false:] only if we are sure no such substitution exists. 1639 * [:false:] only if we are sure no such substitution exists.
1486 */ 1640 */
1487 class PotentialSubtypeVisitor extends SubtypeVisitor { 1641 class PotentialSubtypeVisitor extends SubtypeVisitor {
1488 PotentialSubtypeVisitor(Compiler compiler, 1642 PotentialSubtypeVisitor(Compiler compiler,
1489 DynamicType dynamicType, 1643 DynamicType dynamicType,
1490 VoidType voidType) 1644 VoidType voidType)
1491 : super(compiler, dynamicType, voidType); 1645 : super(compiler, dynamicType, voidType);
1492 1646
1493 1647
1494 bool isSubtype(DartType t, DartType s) { 1648 bool isSubtype(DartType t, DartType s) {
1495 if (t is TypeVariableType || s is TypeVariableType) { 1649 if (t is TypeVariableType || s is TypeVariableType) {
1496 return true; 1650 return true;
1497 } 1651 }
1498 return super.isSubtype(t, s); 1652 return super.isSubtype(t, s);
1499 } 1653 }
1500 } 1654 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698