| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 // The following methods are used to handle type information | 5 // The following methods are used to handle type information |
| 6 // | 6 // |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * @constructor | 9 * @constructor |
| 10 * @param {string} classkey | 10 * @param {string} classkey |
| 11 * @param {string=} typekey | 11 * @param {string=} typekey |
| 12 * @param {Array.<RTT>=} typeargs | 12 * @param {Array.<RTT>=} typeargs |
| 13 * @param {RTT} returnType |
| 14 * @param {bool} functionType |
| 13 */ | 15 */ |
| 14 function RTT(classkey, typekey, typeargs) { | 16 function RTT(classkey, typekey, typeargs, returnType, functionType) { |
| 15 this.classKey = classkey; | 17 this.classKey = classkey; |
| 16 this.typeKey = typekey ? typekey : classkey; | 18 this.typeKey = typekey ? typekey : classkey; |
| 17 this.typeArgs = typeargs; | 19 this.typeArgs = typeargs; |
| 20 this.returnType = returnType; // key for the return type |
| 18 this.implementedTypes = {}; | 21 this.implementedTypes = {}; |
| 22 this.functionType = functionType; |
| 19 // Add self | 23 // Add self |
| 20 this.implementedTypes[classkey] = this; | 24 this.implementedTypes[classkey] = this; |
| 21 // Add Object | 25 // Add Object |
| 22 if (classkey != $cls('Object')) { | 26 if (!functionType && classkey != $cls('Object')) { |
| 23 this.implementedTypes[$cls('Object')] = RTT.objectType; | 27 this.implementedTypes[$cls('Object')] = RTT.objectType; |
| 24 } | 28 } |
| 25 } | 29 } |
| 26 | 30 |
| 27 /** @type {Object.<string, Object>} */ | 31 /** @type {Object.<string, Object>} */ |
| 28 RTT.types = {}; | 32 RTT.types = {}; |
| 29 | 33 |
| 30 /** @type {Array.<RTT>} */ | 34 /** @type {Array.<RTT>} */ |
| 31 RTT.prototype.derivedTypes = []; | 35 RTT.prototype.derivedTypes = []; |
| 32 | 36 |
| 33 /** @return {string} */ | 37 /** @return {string} */ |
| 34 RTT.prototype.toString = function() { return this.typeKey; } | 38 RTT.prototype.toString = function() { return this.typeKey; } |
| 35 | 39 |
| 36 /** | 40 /** |
| 37 * @param {*} value | 41 * @param {*} value |
| 38 * @return {boolean} Whether this type is implemented by the value | 42 * @return {boolean} Whether this type is implemented by the value |
| 39 */ | 43 */ |
| 40 RTT.prototype.implementedBy = function(value){ | 44 RTT.prototype.implementedBy = function(value){ |
| 41 return (value == null) ? RTT.nullInstanceOf(this) : | 45 return (value == null) ? RTT.nullInstanceOf(this) : |
| 46 this.functionType ? this.implementedByTypeFunc(value) : |
| 42 this.implementedByType(RTT.getTypeInfo(value)); | 47 this.implementedByType(RTT.getTypeInfo(value)); |
| 43 }; | 48 }; |
| 44 | 49 |
| 45 /** | 50 /** |
| 46 * A helper function for safely looking up a value | 51 * A helper function for safely looking up a value |
| 47 * in a Object used as a map. | 52 * in a Object used as a map. |
| 48 * @param {Object.<*>} map | 53 * @param {Object.<*>} map |
| 49 * @param {srting} key | 54 * @param {srting} key |
| 50 * @return {*} the value or null; | 55 * @return {*} the value or null; |
| 51 */ | 56 */ |
| 52 function $mapLookup(map, key) { | 57 function $mapLookup(map, key) { |
| 53 return map.hasOwnProperty(key) ? map[key] : null; | 58 return map.hasOwnProperty(key) ? map[key] : null; |
| 54 } | 59 } |
| 55 | 60 |
| 61 RTT.prototype.implementedByTypeSwitch = function(value){ |
| 62 return this.functionType ? this.implementedByTypeFunc(value) : |
| 63 this.implementedByType(value); |
| 64 }; |
| 65 |
| 56 /** | 66 /** |
| 57 * @param {!RTT} other | 67 * @param {!RTT} other |
| 58 * @return {boolean} Whether this type is implement by other | 68 * @return {boolean} Whether this type is implement by other |
| 59 */ | 69 */ |
| 60 RTT.prototype.implementedByType = function(otherType) { | 70 RTT.prototype.implementedByType = function(otherType) { |
| 61 if (otherType === this || otherType === RTT.dynamicType) { | 71 if (otherType === this || otherType === RTT.dynamicType) { |
| 62 return true; | 72 return true; |
| 63 } | 73 } |
| 64 var targetTypeInfo = $mapLookup(otherType.implementedTypes, this.classKey); | 74 var targetTypeInfo = $mapLookup(otherType.implementedTypes, this.classKey); |
| 65 if (targetTypeInfo == null) { | 75 if (targetTypeInfo == null) { |
| 66 return false; | 76 return false; |
| 67 } | 77 } |
| 68 if (targetTypeInfo.typeArgs && this.typeArgs) { | 78 if (targetTypeInfo.typeArgs && this.typeArgs) { |
| 69 for(var i = this.typeArgs.length - 1; i >= 0; i--) { | 79 for(var i = this.typeArgs.length - 1; i >= 0; i--) { |
| 70 if (!this.typeArgs[i].implementedByType(targetTypeInfo.typeArgs[i])) { | 80 if (!this.typeArgs[i].implementedByTypeSwitch(targetTypeInfo.typeArgs[i]))
{ |
| 71 return false; | 81 return false; |
| 72 } | 82 } |
| 73 } | 83 } |
| 74 } | 84 } |
| 75 return true; | 85 return true; |
| 76 }; | 86 }; |
| 77 | 87 |
| 78 /** | 88 /** |
| 89 * @param {!RTT} other |
| 90 * @return {boolean} Whether this type is assignable by other |
| 91 */ |
| 92 RTT.prototype.assignableByType = function(otherType) { |
| 93 if (otherType === this || otherType === RTT.dynamicType || this === RTT.dynami
cType) { |
| 94 return true; |
| 95 } |
| 96 var targetTypeInfo = $mapLookup(otherType.implementedTypes, this.classKey); |
| 97 if (targetTypeInfo == null) { |
| 98 targetTypeInfo = $mapLookup(this.implementedTypes, otherType.classKey); |
| 99 if (targetTypeInfo == null) { |
| 100 return false; |
| 101 } |
| 102 } |
| 103 if (targetTypeInfo.typeArgs && this.typeArgs) { |
| 104 for(var i = this.typeArgs.length - 1; i >= 0; i--) { |
| 105 if (!this.typeArgs[i].assignableByType(targetTypeInfo.typeArgs[i])) { |
| 106 return false; |
| 107 } |
| 108 } |
| 109 } |
| 110 return true; |
| 111 }; |
| 112 |
| 113 |
| 114 /** |
| 115 * @param {!RTT} other |
| 116 * @return {boolean} Whether this type is implemented by other |
| 117 */ |
| 118 RTT.prototype.implementedByTypeFunc = function(otherType) { |
| 119 if (otherType.$lookupRTT) { |
| 120 otherType = otherType.$lookupRTT(); |
| 121 } else if (!(otherType instanceof RTT)) { |
| 122 return false; |
| 123 } |
| 124 if (otherType === this || otherType === RTT.dynamicType) { |
| 125 return true; |
| 126 } |
| 127 var props = Object.getOwnPropertyNames(otherType.implementedTypes); |
| 128 NEXT_PROPERTY: for (var i = 0 ; i < props.length; i++) { |
| 129 var mapped = otherType.implementedTypes[props[i]]; |
| 130 if (mapped.returnType && this.returnType && |
| 131 !this.returnType.assignableByType(mapped.returnType)) { |
| 132 continue; |
| 133 } |
| 134 if (mapped.typeArgs && this.typeArgs) { |
| 135 if (this.typeArgs.length != mapped.typeArgs.length) { |
| 136 continue; |
| 137 } |
| 138 for (var x = this.typeArgs.length - 1; x >= 0; x--) { |
| 139 if (!this.typeArgs[x].assignableByType(mapped.typeArgs[x])) { |
| 140 continue NEXT_PROPERTY; |
| 141 } |
| 142 } |
| 143 } else if (mapped.typeArgs || this.typeArgs) { |
| 144 return false; |
| 145 } |
| 146 return true; |
| 147 } |
| 148 return false; |
| 149 }; |
| 150 |
| 151 /** |
| 79 * @return {string} the class name associated with this type | 152 * @return {string} the class name associated with this type |
| 80 */ | 153 */ |
| 81 RTT.prototype.getClassName = function() { | 154 RTT.prototype.getClassName = function() { |
| 82 var name = this.classKey; | 155 var name = this.classKey; |
| 83 if (name.substr(0, 4) == "cls:") { | 156 if (name.substr(0, 4) == "cls:") { |
| 84 name = name.substr(4); | 157 name = name.substr(4); |
| 85 } | 158 } |
| 86 if (name.substr(-5) == "$Dart") { | 159 if (name.substr(-5) == "$Dart") { |
| 87 name = name.substr(0, name.length - 5); | 160 name = name.substr(0, name.length - 5); |
| 88 } | 161 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 var classkey = RTT.getTypeKey(name); | 200 var classkey = RTT.getTypeKey(name); |
| 128 rtt = new RTT(classkey, typekey, typeArgs); | 201 rtt = new RTT(classkey, typekey, typeArgs); |
| 129 RTT.types[typekey] = rtt; | 202 RTT.types[typekey] = rtt; |
| 130 if (implementsSupplier) { | 203 if (implementsSupplier) { |
| 131 implementsSupplier(rtt, typeArgs); | 204 implementsSupplier(rtt, typeArgs); |
| 132 } | 205 } |
| 133 return rtt; | 206 return rtt; |
| 134 }; | 207 }; |
| 135 | 208 |
| 136 /** | 209 /** |
| 210 * @param {Array.<RTT>=} typeArgs |
| 211 * @param {<RTT>=} returnType (if defined) |
| 212 * @return {RTT} The RTT information object |
| 213 */ |
| 214 RTT.createFunction = function(typeArgs, returnType) { |
| 215 var name = $cls("Function"); |
| 216 var typekey = RTT.getTypeKey(name, typeArgs, returnType); |
| 217 var rtt = $mapLookup(RTT.types, typekey); |
| 218 if (rtt) { |
| 219 return rtt; |
| 220 } |
| 221 var classkey = RTT.getTypeKey(name); |
| 222 rtt = new RTT(classkey, typekey, typeArgs, returnType, true); |
| 223 RTT.types[typekey] = rtt; |
| 224 return rtt; |
| 225 }; |
| 226 |
| 227 /** |
| 137 * @param {string} classkey | 228 * @param {string} classkey |
| 138 * @param {Array.<(RTT|string)>=} typeargs | 229 * @param {Array.<(RTT|string)>=} typeargs |
| 230 * @param {string} returntype |
| 139 * @return {string} | 231 * @return {string} |
| 140 */ | 232 */ |
| 141 RTT.getTypeKey = function(classkey, typeargs) { | 233 RTT.getTypeKey = function(classkey, typeargs, returntype) { |
| 142 var key = classkey; | 234 var key = classkey; |
| 143 if (typeargs) { | 235 if (typeargs) { |
| 144 key += "<" + typeargs.join(",") + ">"; | 236 key += "<" + typeargs.join(",") + ">"; |
| 145 } | 237 } |
| 238 if (returntype) { |
| 239 key += "-><" + returntype + ">"; |
| 240 } |
| 146 return key; | 241 return key; |
| 147 }; | 242 }; |
| 148 | 243 |
| 149 /** | 244 /** |
| 150 * @return {*} value | 245 * @return {*} value |
| 151 * @return {RTT} return the RTT information object for the value | 246 * @return {RTT} return the RTT information object for the value |
| 152 */ | 247 */ |
| 153 RTT.getTypeInfo = function(value) { | 248 RTT.getTypeInfo = function(value) { |
| 154 return (value.$typeInfo) ? value.$typeInfo : RTT.getNativeTypeInfo(value); | 249 return (value.$typeInfo) ? value.$typeInfo : RTT.getNativeTypeInfo(value); |
| 155 }; | 250 }; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 return typeof o == 'number'; | 372 return typeof o == 'number'; |
| 278 } | 373 } |
| 279 | 374 |
| 280 /** | 375 /** |
| 281 * @param {*} o | 376 * @param {*} o |
| 282 * @return {boolean} | 377 * @return {boolean} |
| 283 */ | 378 */ |
| 284 function $isString(o) { | 379 function $isString(o) { |
| 285 return typeof o == 'string'; | 380 return typeof o == 'string'; |
| 286 } | 381 } |
| OLD | NEW |