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

Side by Side Diff: compiler/lib/implementation/rtt.js

Issue 9702034: Removes dartc reliance on its own libraries, now can be targeted at any implementation's libraries (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: junit tests fixed Created 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « compiler/lib/implementation/regexp.js ('k') | compiler/lib/implementation/string.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 // The following methods are used to handle type information
6 //
7
8 /**
9 * @constructor
10 * @param {string} classkey
11 * @param {string=} typekey
12 * @param {Array.<RTT>=} typeargs
13 * @param {RTT} returnType
14 * @param {bool} functionType
15 * @param {string=} named optional
16 */
17 function RTT(classkey, typekey, typeargs, returnType, functionType, named) {
18 this.classKey = classkey;
19 this.typeKey = typekey ? typekey : classkey;
20 this.typeArgs = typeargs;
21 this.returnType = returnType; // key for the return type
22 this.named = named;
23 this.implementedTypes = {};
24 this.functionType = functionType;
25 // Add self
26 this.implementedTypes[classkey] = this;
27 // Add Object
28 if (!functionType && classkey != $cls('Object')) {
29 this.implementedTypes[$cls('Object')] = RTT.objectType;
30 }
31 }
32
33 /** @type {Object.<string, Object>} */
34 RTT.types = {};
35
36 /** @return {string} */
37 RTT.prototype.toString = function() { return this.typeKey; }
38
39 /**
40 * @param {*} value
41 * @return {boolean} Whether this type is implemented by the value
42 */
43 RTT.prototype.implementedBy = function(value){
44 return (value == null) ? RTT.nullInstanceOf(this) :
45 this.functionType ? this.implementedByTypeFunc(value) :
46 this.implementedByType(RTT.getTypeInfo(value));
47 };
48
49 /**
50 * A helper function for safely looking up a value
51 * in a Object used as a map.
52 * @param {Object.<*>} map
53 * @param {srting} key
54 * @return {*} the value or null;
55 */
56 function $mapLookup(map, key) {
57 return map.hasOwnProperty(key) ? map[key] : null;
58 }
59
60 RTT.prototype.implementedByTypeSwitch = function(value){
61 return this.functionType ? this.implementedByTypeFunc(value) :
62 this.implementedByType(value);
63 };
64
65 /**
66 * @param {!RTT} other
67 * @return {boolean} Whether this type is implement by other
68 */
69 RTT.prototype.implementedByType = function(otherType) {
70 if (otherType === this || otherType === RTT.dynamicType.$lookupRTT(null,otherT ype.named)) {
71 return true;
72 }
73 var targetTypeInfo = $mapLookup(otherType.implementedTypes, this.classKey);
74 if (targetTypeInfo == null) {
75 return false;
76 }
77 if (targetTypeInfo.typeArgs && this.typeArgs) {
78 for(var i = this.typeArgs.length - 1; i >= 0; i--) {
79 if (!this.typeArgs[i].implementedByTypeSwitch(targetTypeInfo.typeArgs[i])) {
80 return false;
81 }
82 }
83 }
84 return true;
85 };
86
87 /**
88 * @param {!RTT} other
89 * @return {boolean} Whether this type is assignable by other
90 */
91 RTT.prototype.assignableByType = function(otherType) {
92 if (otherType === this || otherType === RTT.dynamicType.$lookupRTT(null,otherT ype.named)
93 || this === RTT.dynamicType.$lookupRTT(null,this.named)) {
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.$lookupRTT(null,otherT ype.named)) {
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 (mapped.typeArgs.length < this.typeArgs.length) {
136 continue;
137 }
138 var named = false;
139 var x;
140 for (x = 0; x < this.typeArgs.length; x++) {
141 if (this.typeArgs[x].named || mapped.typeArgs[x].named) {
142 named = true;
143 break;
144 }
145 if (!this.typeArgs[x].assignableByType(mapped.typeArgs[x])) {
146 continue NEXT_PROPERTY;
147 }
148 }
149 if (!named && x < this.typeArgs.length) {
150 continue NEXT_PROPERTY;
151 }
152 for (; x < this.typeArgs.length; x++) {
153 if (!this.typeArgs[x].assignableByType(mapped.typeArgs[x])
154 || !(this.typeArgs[x].named === mapped.typeArgs[x].named)) {
155 continue NEXT_PROPERTY;
156 }
157 }
158 } else if (mapped.typeArgs || this.typeArgs) {
159 continue NEXT_PROPERTY;
160 }
161 return true;
162 }
163 return false;
164 };
165
166 /**
167 * @return {string} the class name associated with this type
168 */
169 RTT.prototype.getClassName = function() {
170 var name = this.classKey;
171 if (name.substr(0, 4) == "cls:") {
172 name = name.substr(4);
173 }
174 if (name.substr(-5) == "$Dart") {
175 name = name.substr(0, name.length - 5);
176 }
177 return name;
178 }
179
180 /**
181 * @param {RTT}
182 * @return {boolean}
183 */
184 RTT.nullInstanceOf = function(type) {
185 return type === RTT.objectType || type === RTT.dynamicType.$lookupRTT(null,typ e.named);
186 };
187
188 /**
189 * @param {*} value The value to retrieve type information for
190 * @return {RTT}
191 */
192 RTT.getNativeTypeInfo = function(value) {
193 if (value instanceof Array) return Array.$lookupRTT();
194 switch (typeof value) {
195 case 'string': return String.$lookupRTT();
196 case 'number': return Number.$lookupRTT();
197 case 'boolean': return Boolean.$lookupRTT();
198 }
199 return RTT.placeholderType;
200 };
201
202 /**
203 * @param {string} name
204 * @param {function(RTT,Array.<RTT>)=} implementsSupplier
205 * @param {Array.<RTT>=} typeArgs
206 * @param {string} named optional value
207 * @return {RTT} The RTT information object
208 */
209 RTT.create = function(name, implementsSupplier, typeArgs, named) {
210 if (name == $cls("Object") && !named) return RTT.objectType;
211 var typekey = RTT.getTypeKey(name, typeArgs, null, named);
212 var rtt = $mapLookup(RTT.types, typekey);
213 if (rtt) {
214 return rtt;
215 }
216 var classkey = RTT.getTypeKey(name);
217 rtt = new RTT(classkey, typekey, typeArgs, null, false, named);
218 RTT.types[typekey] = rtt;
219 if (implementsSupplier) {
220 implementsSupplier(rtt, typeArgs);
221 }
222 return rtt;
223 };
224
225 /**
226 * @param {Array.<RTT>=} typeArgs
227 * @param {<RTT>=} returnType (if defined)
228 * @param {string} named optional value
229 * @return {RTT} The RTT information object
230 */
231 RTT.createFunction = function(typeArgs, returnType, named) {
232 var name = $cls("Function$Dart");
233 var typekey = RTT.getTypeKey(name, typeArgs, returnType, named);
234 var rtt = $mapLookup(RTT.types, typekey);
235 if (rtt) {
236 return rtt;
237 }
238 var classkey = RTT.getTypeKey(name);
239 rtt = new RTT(classkey, typekey, typeArgs, returnType, true, named);
240 RTT.types[typekey] = rtt;
241 return rtt;
242 };
243
244 /**
245 * @param {RTT} old
246 * @param {string} named optional
247 * @return {RTT} The RTT information object with named
248 */
249 RTT.clone = function(old, named) {
250 var name = old.getClassName();
251 var typekey = RTT.getTypeKey(name, old.typeArgs, old.returnType, named);
252 var rtt = $mapLookup(RTT.types, typekey);
253 if (rtt) {
254 return rtt;
255 }
256 var classkey = RTT.getTypeKey(name);
257 rtt = new RTT(classkey, typekey, old.typeArgs, old.returnType, old.functionTyp e, named);
258 RTT.types[typekey] = rtt;
259 rtt.implementedTypes = old.implementedTypes
260 return rtt;
261 };
262
263 /**
264 * @param {string} classkey
265 * @param {Array.<(RTT|string)>=} typeargs
266 * @param {string} returntype
267 * @param {string=} named optional
268 * @return {string}
269 */
270 RTT.getTypeKey = function(classkey, typeargs, returntype, named) {
271 var key = classkey;
272 if (named) {
273 key += ":" + named;
274 }
275 if (typeargs) {
276 key += "<" + typeargs.join(",") + ">";
277 }
278 if (returntype) {
279 key += "-><" + returntype + ">";
280 }
281 return key;
282 };
283
284 /**
285 * @return {*} value
286 * @return {RTT} return the RTT information object for the value
287 */
288 RTT.getTypeInfo = function(value) {
289 return (value.$typeInfo) ? value.$typeInfo : RTT.getNativeTypeInfo(value);
290 };
291
292 /**
293 * @param {Object} o
294 * @param {RTT} rtt
295 * Sets the RTT on the object and returns the object itself.
296 */
297 RTT.setTypeInfo = function(o, rtt) {
298 o.$typeInfo = rtt;
299 return o;
300 };
301
302 /**
303 * @param {Object} o
304 * Removes any RTT from the object and returns the object itself.
305 */
306 RTT.removeTypeInfo = function(o) {
307 o.$typeInfo = null;
308 return o;
309 };
310
311 /**
312 * The typeArg array is optional
313 * @param {Array.<RTT>=} typeArgs
314 * @param {number} i
315 * @param {string=} named optional
316 * @return {RTT}
317 */
318 RTT.getTypeArg = function(typeArgs, i, named) {
319 if (typeArgs) {
320 if (typeArgs.length > i) {
321 if (named && named != typeArgs[i].named) {
322 return RTT.clone(typeArgs[i], named);
323 }
324 return typeArgs[i];
325 } else {
326 throw new Error("Missing type arg");
327 }
328 }
329 return RTT.dynamicType.$lookupRTT(null,named);
330 };
331
332 /**
333 * The typeArg array is optional
334 * @param {*} o
335 * @param {string} classkey
336 * @return {Array.<RTT>}
337 */
338 RTT.getTypeArgsFor = function(o, classkey) {
339 var rtt = $mapLookup(RTT.getTypeInfo(o).implementedTypes, classkey);
340 if (!rtt) {
341 throw new Error("internal error: can not find " +
342 classkey + " in " + JSON.stringify(o));
343 }
344 return rtt.typeArgs;
345 };
346
347 // Base types for runtime type information
348
349 /** @type {!RTT} */
350 function ImplementsAll(name,named) {
351 var typeKey = RTT.getTypeKey(name, null, null, named);
352 RTT.call(this,name,typeKey,null,null,null,named);
353 }
354 $inherits(ImplementsAll,RTT);
355 ImplementsAll.prototype.implementedBy = function(o) {return true};
356 ImplementsAll.prototype.implementedByType = function(o) {return true};
357
358 RTT.objectType = new ImplementsAll($cls('Object'));
359 RTT.placeholderType = new ImplementsAll($cls('::'));
360
361 function ImplementsDynamic(named) {
362 ImplementsAll.call(this,$cls('Dynamic'),named);
363 }
364 $inherits(ImplementsDynamic,ImplementsAll);
365 ImplementsDynamic.prototype.$lookupRTT = function(typeArgs, named) {
366 var typekey = RTT.getTypeKey($cls('Dynamic'), null, null, named);
367 var rtt = $mapLookup(RTT.types, typekey);
368 if (rtt) {
369 return rtt;
370 }
371 rtt = new ImplementsDynamic(named);
372 RTT.types[typekey] = rtt;
373 return rtt;
374 }
375 RTT.dynamicType = ImplementsDynamic.prototype.$lookupRTT();
376
377 /**
378 * Checks that a value is assignable to an expected type, and either returns tha t
379 * value if it is, or else throws a TypeMismatchException.
380 *
381 * @param {!RTT} the expected type
382 * @param {*} the value to check
383 * @return {*} the value
384 */
385 function $chk(rtt, value) {
386 // null can be assigned to any type
387 if (value == $Dart$Null || rtt.implementedBy(value)) {
388 return value;
389 }
390 $te(rtt, value);
391 }
392
393 /**
394 * Throw a TypeError. See core.dart for the ExceptionHelper class.
395 *
396 * @param {!RTT} the expected type
397 * @param {*) the value that failed
398 */
399 function $te(rtt, value) {
400 var srcType = RTT.getTypeInfo(value).getClassName();
401 var dstType = rtt.getClassName();
402 var e = native_ExceptionHelper_createTypeError(srcType, dstType);
403 $Dart$ThrowException(e);
404 }
405
406 // Setup the Function object
407 Function.prototype.$implements$Function$Dart = 1;
408 RTT.setTypeInfo(Function.prototype, RTT.create($cls('Function$Dart')));
409
410 /**
411 * @param {string} cls
412 * @return {string}
413 * @consistentIdGenerator
414 */
415 function $cls(cls) {
416 return "cls:" + cls;
417 }
418
419 /**
420 * @param {*} o
421 * @return {boolean}
422 */
423 function $isBool(o) {
424 return typeof o == 'boolean';
425 }
426
427 /**
428 * @param {*} o
429 * @return {boolean}
430 */
431 function $isNum(o) {
432 return typeof o == 'number';
433 }
434
435 /**
436 * @param {*} o
437 * @return {boolean}
438 */
439 function $isString(o) {
440 return typeof o == 'string';
441 }
OLDNEW
« no previous file with comments | « compiler/lib/implementation/regexp.js ('k') | compiler/lib/implementation/string.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698