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

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

Issue 12210142: Implement is-checks against type variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 10 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 | 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 _js_helper; 5 library _js_helper;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS, 8 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS,
9 JS, 9 JS,
10 JS_CALL_IN_ISOLATE, 10 JS_CALL_IN_ISOLATE,
(...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 } 1534 }
1535 } 1535 }
1536 return true; 1536 return true;
1537 } 1537 }
1538 1538
1539 getArguments(var type) => JS('var', r'#.slice(1)', type); 1539 getArguments(var type) => JS('var', r'#.slice(1)', type);
1540 1540
1541 getField(var object, var name) => JS('var', r'#[#]', object, name); 1541 getField(var object, var name) => JS('var', r'#[#]', object, name);
1542 1542
1543 /** 1543 /**
1544 * Tests whether the Dart object [o] is a subtype of the runtime type
1545 * representation [t], which is a type representation as described in the
1546 * comment on [isSubtype].
1547 */
1548 bool objectIsSubtype(Object o, var t) {
1549 if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
1550 // In the case of [List], [t] will be an array with the type representation
1551 // in the first entry and the type argument in the second.
1552 var typeOfT = isJsArray(t) ? getField(t, 0) : t;
1553 var nativeCheck = getField(typeOfT, '\$nativeCheck');
1554 if (nativeCheck != null) {
1555 bool isInstance = invoke(nativeCheck, [o]);
1556 if (!isInstance) return false;
1557 if (o is List) {
1558 // If the object is a list and passed the native check, we know that [t]
1559 // is an array containing the type argument as its second entry.
1560 return isSubtype(getRuntimeTypeArgument(o, null, 0), getField(t, 1));
1561 }
1562 return true;
1563 } else {
1564 var type;
1565 var rti = getRuntimeTypeInfo(o);
1566 // If the type has type variables (that is, [:rti != null:]), make a copy of
1567 // the type arguments and insert [o] in the first position to create a
1568 // compound type representation, otherwise use [o] itself.
1569 if (JS('bool', '# != null', rti)) {
1570 type = JS('List', '#.slice().splice(0, 0, #)', rti, o);
1571 } else {
1572 // We can use the object as its own type representation because we install
1573 // the subtype flags and the substitution on the prototype, so they are
1574 // properties of the object in JS.
1575 type = o;
1576 }
1577 return isSubtype(type, t);
1578 }
1579 }
1580
1581
1582 /**
1544 * Check whether the type represented by [s] is a subtype of the type 1583 * Check whether the type represented by [s] is a subtype of the type
1545 * represented by [t]. 1584 * represented by [t].
1546 * 1585 *
1547 * Type representations can be: 1586 * Type representations can be:
1548 * 1) a JavaScript constructor for a class C: the represented type is the raw 1587 * 1) a JavaScript constructor for a class C: the represented type is the raw
1549 * type C. 1588 * type C.
1550 * 2) a JavaScript object: this represents a class for which there is no 1589 * 2) a Dart object.
1590 * 3) a JavaScript object: this represents a class for which there is no
1551 * JavaScript constructor, because it is only used in type arguments or it 1591 * JavaScript constructor, because it is only used in type arguments or it
1552 * is native. The represented type is the raw type of this class. 1592 * is native. The represented type is the raw type of this class.
1553 * 3) a JavaScript array: the first entry is of type 1 or 2 and identifies the 1593 * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
1554 * class of the type and the rest of the array are the type arguments. 1594 * subtyping flags and the substitution of the type and the rest of the
1555 * 4) [:null:]: the dynamic type. 1595 * array are the type arguments.
1596 * 5) [:null:]: the dynamic type.
1556 */ 1597 */
1557 bool isSubtype(var s, var t) { 1598 bool isSubtype(var s, var t) {
1558 // If either type is dynamic, [s] is a subtype of [t]. 1599 // If either type is dynamic, [s] is a subtype of [t].
1559 if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true; 1600 if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
1560 // Subtyping is reflexive. 1601 // Subtyping is reflexive.
1561 if (JS('bool', '# === #', s, t)) return true; 1602 if (JS('bool', '# === #', s, t)) return true;
1562 // Get the object describing the class and check for the subtyping flag 1603 // Get the object describing the class and check for the subtyping flag
1563 // constructed from the type of [t]. 1604 // constructed from the type of [t].
1564 var typeOfS = isJsArray(s) ? s[0] : s; 1605 var typeOfS = isJsArray(s) ? s[0] : s;
1565 var typeOfT = isJsArray(t) ? t[0] : t; 1606 var typeOfT = isJsArray(t) ? t[0] : t;
1566 // Check for a subtyping flag. 1607 // Check for a subtyping flag.
1567 var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}'; 1608 var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
1568 if (getField(typeOfS, test) == null) return false; 1609 if (getField(typeOfS, test) == null) return false;
1569 // The class of [s] is a subclass of the class of [t]. If either of the types 1610 // The class of [s] is a subclass of the class of [t]. If either of the types
1570 // is raw, [s] is a subtype of [t]. 1611 // is raw, [s] is a subtype of [t].
1571 if (!isJsArray(s) || !isJsArray(t)) return true; 1612 if (!isJsArray(s) || !isJsArray(t)) return true;
1572 // Get the necessary substitution of the type arguments, if there is one. 1613 // Get the necessary substitution of the type arguments, if there is one.
1573 var substitution; 1614 var substitution;
1574 if (JS('bool', '# !== #', typeOfT, typeOfS)) { 1615 if (JS('bool', '# !== #', typeOfT, typeOfS)) {
1575 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; 1616 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
1576 substitution = getField(typeOfS, field); 1617 substitution = getField(typeOfS, field);
1577 } 1618 }
1578 // Recursively check the type arguments. 1619 // Recursively check the type arguments.
1579 return checkArguments(substitution, getArguments(s), getArguments(t)); 1620 return checkArguments(substitution, getArguments(s), getArguments(t));
1580 } 1621 }
1581 1622
1582 createRuntimeType(String name) => new TypeImpl(name); 1623 createRuntimeType(String name) => new TypeImpl(name);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698