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

Unified Diff: lib/runtime/_types.js

Issue 1195523002: Handle dynamic as bottom inside of function type reps (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Fix typo in comment Created 5 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
« no previous file with comments | « lib/runtime/_rtti.js ('k') | lib/runtime/dart/_foreign_helper.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/runtime/_types.js
diff --git a/lib/runtime/_types.js b/lib/runtime/_types.js
index e8dc2d0c38c034a33867abc9f5b2719181fa7fb5..af5e2d04d24fce2fe1fdf0f7c351b3816aaed66a 100644
--- a/lib/runtime/_types.js
+++ b/lib/runtime/_types.js
@@ -19,6 +19,32 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
const copyProperties = dart_utils.copyProperties;
const safeGetOwnProperty = dart_utils.safeGetOwnProperty;
+ /**
+ * Types in dart are represented at runtime as follows.
+ * - Normal nominal types, produced from classes, are represented
+ * at runtime by the JS class of which they are an instance.
+ * If the type is the result of instantiating a generic class,
+ * then the "classes" module manages the association between the
+ * instantiated class and the original class declaration
+ * and the type arguments with which it was instantiated. This
+ * assocation can be queried via the "classes" module".
+ *
+ * - All other types are represented as instances of class TypeRep,
+ * defined in this module.
+ * - Dynamic, Void, and Bottom are singleton instances of sentinal
+ * classes.
+ * - Function types are instances of subclasses of AbstractFunctionType.
+ *
+ * Function types are represented in one of two ways:
+ * - As an instance of FunctionType. These are eagerly computed.
+ * - As an instance of TypeDef. The TypeDef representation lazily
+ * computes an instance of FunctionType, and delegates to that instance.
+ *
+ * All types satisfy the following interface:
+ * get String name;
+ * String toString();
+ *
+ */
class TypeRep extends rtti.LazyTagged(() => core.Type) {
get name() {return this.toString();}
}
@@ -90,12 +116,51 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
}
class FunctionType extends AbstractFunctionType {
- constructor(returnType, args, optionals, named) {
+ /**
+ * Construct a function type. There are two arrow constructors,
+ * distinguished by the "definite" flag.
+ *
+ * The fuzzy arrow (definite is false) treats any arguments
+ * of type dynamic as having type bottom, and will always be
+ * called with a dynamic invoke.
+ *
+ * The definite arrow (definite is true) leaves arguments unchanged.
+ *
+ * We eagerly canonize the argument types to avoid having to deal with
+ * this logic in multiple places.
+ *
+ * TODO(leafp): Figure out how to present this to the user. How
+ * should these be printed out?
+ */
+ constructor(definite, returnType, args, optionals, named) {
super();
+ this.definite = definite;
this.returnType = returnType;
this.args = args;
this.optionals = optionals;
this.named = named;
+ this._canonize();
+ }
+ _canonize() {
+ if (this.definite) return;
+
+ function replace(a) {
+ return (a == dynamicR) ? bottomR : a;
+ }
+
+ this.args = this.args.map(replace);
+
+ if (this.optionals.length > 0) {
+ this.optionals = this.optionals.map(replace);
+ }
+
+ if (Object.keys(this.named).length > 0) {
+ let r = {};
+ for (let name of getOwnPropertyNames(this.named)) {
+ r[name] = replace(this.named[name]);
+ }
+ this.named = r;
+ }
}
}
@@ -107,6 +172,10 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
this._functionType = null;
}
+ get definite() {
+ return this._functionType.definite;
+ }
+
get name() {
return this._name;
}
@@ -135,7 +204,7 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
}
}
- function functionType(returnType, args, extra) {
+ function _functionType(definite, returnType, args, extra) {
// TODO(vsm): Cache / memomize?
let optionals;
let named;
@@ -149,10 +218,27 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
optionals = [];
named = extra;
}
- return new FunctionType(returnType, args, optionals, named);
+ return new FunctionType(definite, returnType, args, optionals, named);
+ }
+
+ /**
+ * Create a "fuzzy" function type. If any arguments are dynamic
+ * they will be replaced with bottom.
+ */
+ function functionType(returnType, args, extra) {
+ return _functionType(false, returnType, args, extra);
}
exports.functionType = functionType;
+ /**
+ * Create a definite function type. No substitution of dynamic for
+ * bottom occurs.
+ */
+ function definiteFunctionType(returnType, args, extra) {
+ return _functionType(true, returnType, args, extra);
+ }
+ exports.definiteFunctionType = definiteFunctionType;
+
function typedef(name, closure) {
return new Typedef(name, closure);
}
@@ -218,7 +304,7 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
}
for (let i = 0; i < args1.length; ++i) {
- if (!isSubtype_(args2[i], args1[i], true)) {
+ if (!isSubtype_(args2[i], args1[i])) {
return false;
}
}
@@ -232,13 +318,13 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
let j = 0;
for (let i = args1.length; i < args2.length; ++i, ++j) {
- if (!isSubtype_(args2[i], optionals1[j], true)) {
+ if (!isSubtype_(args2[i], optionals1[j])) {
return false;
}
}
for (let i = 0; i < optionals2.length; ++i, ++j) {
- if (!isSubtype_(optionals2[i], optionals1[j], true)) {
+ if (!isSubtype_(optionals2[i], optionals1[j])) {
return false;
}
}
@@ -254,7 +340,7 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
if (n1 === void 0) {
return false;
}
- if (!isSubtype_(n2, n1, true)) {
+ if (!isSubtype_(n2, n1)) {
return false;
}
}
@@ -298,33 +384,26 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
}
exports.isSubtype = isSubtype;
- function _isBottom(type, dynamicIsBottom) {
- return (type == dynamicR && dynamicIsBottom) || type == bottomR;
+ function _isBottom(type) {
+ return type == bottomR;
}
- function _isTop(type, dynamicIsBottom) {
- return type == core.Object || (type == dynamicR && !dynamicIsBottom);
+ function _isTop(type) {
+ return type == core.Object || (type == dynamicR);
}
- function isSubtype_(t1, t2, opt_dynamicIsBottom) {
- let dynamicIsBottom =
- opt_dynamicIsBottom === void 0 ? false : opt_dynamicIsBottom;
-
+ function isSubtype_(t1, t2) {
t1 = canonicalType(t1);
t2 = canonicalType(t2);
if (t1 == t2) return true;
- // In Dart, dynamic is effectively both top and bottom.
- // Here, we treat dynamic as one or the other depending on context,
- // but not both.
-
// Trivially true.
- if (_isTop(t2, dynamicIsBottom) || _isBottom(t1, dynamicIsBottom)) {
+ if (_isTop(t2) || _isBottom(t1)) {
return true;
}
// Trivially false.
- if (_isTop(t1, dynamicIsBottom) || _isBottom(t2, dynamicIsBottom)) {
+ if (_isTop(t1) || _isBottom(t2)) {
return false;
}
@@ -413,16 +492,16 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[
// TODO(vsm): Cache this if we start using it at runtime.
if (type instanceof AbstractFunctionType) {
- if (!_isTop(type.returnType, false)) return false;
+ if (!_isTop(type.returnType)) return false;
for (let i = 0; i < type.args.length; ++i) {
- if (!_isBottom(type.args[i], true)) return false;
+ if (!_isBottom(type.args[i])) return false;
}
for (let i = 0; i < type.optionals.length; ++i) {
- if (!_isBottom(type.optionals[i], true)) return false;
+ if (!_isBottom(type.optionals[i])) return false;
}
let names = getOwnPropertyNames(type.named);
for (let i = 0; i < names.length; ++i) {
- if (!_isBottom(type.named[names[i]], true)) return false;
+ if (!_isBottom(type.named[names[i]])) return false;
}
return true;
}
« no previous file with comments | « lib/runtime/_rtti.js ('k') | lib/runtime/dart/_foreign_helper.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698