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

Unified Diff: pkg/dev_compiler/lib/src/compiler/js_typerep.dart

Issue 2926613003: Generate better code for '=='. (Closed)
Patch Set: Address comments Created 3 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: pkg/dev_compiler/lib/src/compiler/js_typerep.dart
diff --git a/pkg/dev_compiler/lib/src/compiler/js_typerep.dart b/pkg/dev_compiler/lib/src/compiler/js_typerep.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2d73cb049eff6cfe33703d074e961817514c9fce
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/compiler/js_typerep.dart
@@ -0,0 +1,154 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/type_system.dart'
+ show StrongTypeSystemImpl;
+
+/// An abstraction of the JS types
+abstract class JSType {
+ const JSType();
+
+ /// True if this type is built-in to JS, and we use the values unwrapped.
+ /// For these types we generate a calling convention via static
+ /// "extension methods". This allows types to be extended without adding
+ /// extensions directly on the prototype.
+ bool get isPrimitive;
+
+ /// Is this type known to be definitively primitive
+ /// (using the JS notion of primitive)
+ bool get isPrimitiveInJS;
+
+ /// Can a non-null element of this type potentially be interpreted
+ /// as false in JS.
+ bool get isFalsey;
+
+ static const jsBoolean = const JSBoolean();
+ static const jsNumber = const JSNumber();
+ static const jsNull = const JSNull();
+ static const jsObject = const JSObject();
+ static const jsString = const JSString();
+ static const jsUnknown = const JSUnknown();
+}
+
+/// Inhabited by booleans (including JSBool), null, and undefined
+class JSBoolean extends JSType {
+ const JSBoolean();
+ bool get isPrimitive => true;
+ bool get isPrimitiveInJS => true;
+ bool get isFalsey => true;
+}
+
+/// Inhabited by numbers, null, and undefined
+/// In practice, this is 4 types: num, int, double, and _interceptors.JSNumber.
+///
+/// _interceptors.JSNumber is the type that actually "implements" all numbers,
+/// hence it's a subtype of int and double (and num).
+/// It's defined in our "dart:_interceptors".
+class JSNumber extends JSType {
+ const JSNumber();
+ bool get isPrimitive => true;
+ bool get isPrimitiveInJS => true;
+ bool get isFalsey => true;
+}
+
+/// Inhabited by null and undefined
+class JSNull extends JSType {
+ const JSNull();
+ bool get isPrimitive => false;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => true;
+}
+
+/// Inhabited by objects, null, and undefined
+class JSObject extends JSType {
+ const JSObject();
+ bool get isPrimitive => false;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => false;
+}
+
+/// Inhabited by strings (including JSString), null, and undefined
+class JSString extends JSType {
+ const JSString();
+ bool get isPrimitive => true;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => true;
+}
+
+/// Inhabitance not statically known
+class JSUnknown extends JSType {
+ const JSUnknown();
+ bool get isPrimitive => false;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => true;
+}
+
+class JSTypeRep {
+ final StrongTypeSystemImpl rules;
+ final TypeProvider types;
+
+ JSTypeRep(this.rules, this.types);
+
+ JSType typeFor(DartType type) {
+ while (type is TypeParameterType) {
+ type = (type as TypeParameterType).element.bound;
+ }
+ if (type == null) return JSType.jsUnknown;
+ if (type.isDartCoreNull) return JSType.jsNull;
+ // Note that this should be changed if Dart gets non-nullable types
+ if (type.isBottom) return JSType.jsNull;
+ if (rules.isSubtypeOf(type, types.numType)) return JSType.jsNumber;
+ if (rules.isSubtypeOf(type, types.boolType)) return JSType.jsBoolean;
+ if (rules.isSubtypeOf(type, types.stringType)) return JSType.jsString;
+ if (type.isDartAsyncFutureOr) {
+ var argument = (type as InterfaceType).typeArguments[0];
+ var argumentRep = typeFor(argument);
+ if (argumentRep is JSObject || argumentRep is JSNull) {
+ return JSType.jsObject;
+ }
+ return JSType.jsUnknown;
+ }
+ if (type.isDynamic || type.isObject || type.isVoid) return JSType.jsUnknown;
+ return JSType.jsObject;
+ }
+
+ /// If the type [t] is [int] or [double], or a type parameter
+ /// bounded by [int], [double] or [num] returns [num].
+ /// Otherwise returns [t].
+ DartType canonicalizeNumTypes(DartType t) => isNumber(t) ? types.numType : t;
+
+ bool isNumber(DartType type) => typeFor(type) is JSNumber;
+
+ /// Is this type known to be represented as Object or Null in JS.
+ bool isObjectOrNull(DartType t) {
+ var rep = typeFor(t);
+ return rep is JSObject || rep is JSNull;
+ }
+
+ bool isUnknown(DartType t) => typeFor(t) is JSUnknown;
+
+ bool isPrimitive(DartType t) => typeFor(t).isPrimitive;
+
+ bool isPrimitiveInJS(DartType t) => typeFor(t).isPrimitiveInJS;
+
+ bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
+ isPrimitiveInJS(leftT) && isPrimitiveInJS(rightT);
+
+ bool unaryOperationIsPrimitive(DartType t) => isPrimitiveInJS(t);
+
+ /// True if the JS double equals (`==`) comparison on the representation
+ /// of these two types could potentially cause a conversion.
+ bool equalityMayConvert(DartType t0, DartType t1) => !equalOrNull(t0, t1);
+
+ // Are t0 and t1 known to either be represented by the same type
+ // or else one or both of them is represented by Null
+ bool equalOrNull(DartType t0, DartType t1) {
+ var rep0 = typeFor(t0);
+ var rep1 = typeFor(t1);
+ if (rep0 is JSNull || rep1 is JSNull) return true;
+ return rep0 == rep1 && rep0 is! JSUnknown;
+ }
+}
« no previous file with comments | « pkg/dev_compiler/lib/src/compiler/code_generator.dart ('k') | pkg/dev_compiler/test/codegen/identity_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698