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

Unified Diff: sdk/lib/_internal/compiler/implementation/lib/js_helper.dart

Issue 12334070: Support runtime check of function types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Register dependency Created 7 years, 9 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: sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index e4536f3622aca4ed21dc7eeb3a2b8fc849153a19..3657858d89dd7fc1a0cf1e7a9df4d46fc91ab035 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -1049,6 +1049,12 @@ getRuntimeTypeInfo(target) {
return JS('var', r'#.$builtinTypeInfo', target);
}
+forwardRuntimeTypeInfo(target, substitution, source) {
+ setRuntimeTypeInfo(target,
+ substitute(substitution, getRuntimeTypeInfo(source)));
+ return target;
+}
+
getRuntimeTypeArgument(target, substitution, index) {
var arguments = substitute(substitution, getRuntimeTypeInfo(target));
return (arguments == null) ? null : getField(arguments, index);
@@ -1472,6 +1478,8 @@ String getRuntimeTypeString(var object) {
bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
+bool isJsObject(var o) => JS('bool', r"typeof # == 'object'", o);
+
Object invoke(function, arguments) {
return JS('var', r'#.apply(null, #)', function, arguments);
}
@@ -1497,6 +1505,26 @@ bool checkArguments(var substitution, var arguments, var checks) {
return areSubtypes(substitute(substitution, arguments), checks);
}
+bool getSignature(var signature, var target) {
+ return invoke(signature, getRuntimeTypeInfo(target));
+}
+
+bool checkFunctionSubtype(var target, var typeSignature, var context) {
+ var targetSignature = getField(target, r'$signature');
ngeoffray 2013/03/13 09:30:46 Using $signature directly is brittle, you should p
Johnni Winther 2013/03/22 07:30:24 Done.
+ if (targetSignature == null) {
+ // The target is statically known to be a subtype so further check is
ngeoffray 2013/03/13 09:30:46 further or no further? Could you add an example?
Johnni Winther 2013/03/22 07:30:24 Not needed in the new encoding.
+ // needed.
+ return true;
+ }
+ if (isJsFunction(targetSignature)) {
+ targetSignature = invoke(targetSignature, getRuntimeTypeInfo(target));
+ }
+ if (isJsFunction(typeSignature)) {
+ typeSignature = invoke(typeSignature, getRuntimeTypeInfo(context));
+ }
+ return isFunctionSubtype(targetSignature, typeSignature);
+}
+
bool areSubtypes(List s, List t) {
// [:null:] means a raw type.
if (s == null || t == null) return true;
@@ -1571,6 +1599,9 @@ bool isSubtype(var s, var t) {
if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
// Subtyping is reflexive.
if (JS('bool', '# === #', s, t)) return true;
+ if (getField(t, 'func') == true) {
ngeoffray 2013/03/13 09:30:46 What is this? Probably needs an abstraction.
Johnni Winther 2013/03/22 07:30:24 A tag used to identify function type representatio
+ return isFunctionSubtype(s, t);
+ }
// Get the object describing the class and check for the subtyping flag
// constructed from the type of [t].
var typeOfS = isJsArray(s) ? s[0] : s;
@@ -1596,4 +1627,79 @@ bool isSubtype(var s, var t) {
return checkArguments(substitution, getArguments(s), getArguments(t));
}
+bool isAssignable(var s, var t) {
+ return isSubtype(s, t) || isSubtype(t, s);
+}
+
+bool areAssignable(List s, List t, bool allowSubset) {
+ if (t == null) return true;
+ if (s == null) return false;
+
+ assert(isJsArray(s));
+ assert(isJsArray(t));
+
+ if (allowSubset) {
+ if (s.length < t.length) return false;
+ } else {
+ if (s.length != t.length) return false;
+ }
+
+ int len = t.length;
+ for (int i = 0; i < len; i++) {
+ if (!isAssignable(s[i], t[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool areAssignableMaps(var s, var t) {
+ if (t == null) return true;
+ if (s == null) return false;
+
+ assert(isJsObject(s));
+ assert(isJsObject(t));
+
+ // Hack: We need to iterate over the properties in [t], and the names of these
+ // properties are not statically known so they must be retrieved dynamically.
+ // Therefore we (mis)use the [JS] function to generate a for-each loop on [t]
+ // using the JavaScript variable [:$name:] to hold the property names.
ngeoffray 2013/03/13 09:30:46 To not make it a hack, please create a JavaScript
Johnni Winther 2013/03/22 07:30:24 How?
+ JS('', r'for (var $name in #) {', t); {
+ // We need to distinguish the existing property with value [:undefined:] or
+ // [:null:] from the non-existing property. The former is interpreted as a
+ // named parameter of type [:dynamic:] and the later is interpreted as
+ // [:$name:] not being a named parameter of [s].
+ if (JS('bool', r'!#.hasOwnProperty($name)', s)) return false;
+ var tType = JS('', r'#[$name]', t);
+ var sType = JS('', r'#[$name]', s);
+ if (!isAssignable(sType, tType)) {
+ return false;
+ }
+ } JS('', '}');
+ return true;
+}
+
+bool isFunctionSubtype(var s, var t) {
+ if (!getField(s, 'func')) return false;
+ if (getField(s, 'retvoid')) {
+ if (!getField(t, 'retvoid')) return false;
+ } else if (!getField(t, 'retvoid')) {
+ var sReturnType = getField(s, 'ret');
+ var tReturnType = getField(t, 'ret');
+ if (!isAssignable(sReturnType, tReturnType)) return false;
+ }
+ var sParameterTypes = getField(s, 'args');
+ var tParameterTypes = getField(t, 'args');
+ if (!areAssignable(sParameterTypes, tParameterTypes, false)) return false;
+ var sOptionalParameterTypes = getField(s, 'opt');
+ var tOptionalParameterTypes = getField(t, 'opt');
+ if (!areAssignable(sOptionalParameterTypes, tOptionalParameterTypes, true)) {
+ return false;
+ }
+ var sNamedParameters = getField(s, 'named');
+ var tNamedParameters = getField(t, 'named');
+ if (!areAssignableMaps(sNamedParameters, tNamedParameters)) return false;
+ return true;
+}
+
createRuntimeType(String name) => new TypeImpl(name);

Powered by Google App Engine
This is Rietveld 408576698