OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of dart2js; | 5 part of dart2js; |
6 | 6 |
7 class TypeCheckerTask extends CompilerTask { | 7 class TypeCheckerTask extends CompilerTask { |
8 TypeCheckerTask(Compiler compiler) : super(compiler); | 8 TypeCheckerTask(Compiler compiler) : super(compiler); |
9 String get name => "Type checker"; | 9 String get name => "Type checker"; |
10 | 10 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 * name is bound. The unaliased version of any other type is the type itself. | 80 * name is bound. The unaliased version of any other type is the type itself. |
81 * | 81 * |
82 * For example, the unaliased type of [: typedef A Func<A,B>(B b) :] is the | 82 * For example, the unaliased type of [: typedef A Func<A,B>(B b) :] is the |
83 * function type [: (B) -> A :] and the unaliased type of | 83 * function type [: (B) -> A :] and the unaliased type of |
84 * [: Func<int,String> :] is the function type [: (String) -> int :]. | 84 * [: Func<int,String> :] is the function type [: (String) -> int :]. |
85 */ | 85 */ |
86 DartType unalias(Compiler compiler); | 86 DartType unalias(Compiler compiler); |
87 | 87 |
88 bool operator ==(other); | 88 bool operator ==(other); |
89 | 89 |
| 90 /** |
| 91 * Is [: true :] if this type has no explict type arguments. |
| 92 */ |
| 93 bool get isRaw => true; |
| 94 |
90 DartType asRaw() => this; | 95 DartType asRaw() => this; |
91 } | 96 } |
92 | 97 |
93 /** | 98 /** |
94 * Represents a type variable, that is the type parameters of a class type. | 99 * Represents a type variable, that is the type parameters of a class type. |
95 * | 100 * |
96 * For example, in [: class Array<E> { ... } :], E is a type variable. | 101 * For example, in [: class Array<E> { ... } :], E is a type variable. |
97 * | 102 * |
98 * Each class should have its own unique type variables, one for each type | 103 * Each class should have its own unique type variables, one for each type |
99 * parameter. A class with type parameters is said to be parameterized or | 104 * parameter. A class with type parameters is said to be parameterized or |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 DartType unalias(Compiler compiler) => this; | 262 DartType unalias(Compiler compiler) => this; |
258 | 263 |
259 int get hashCode => 1733; | 264 int get hashCode => 1733; |
260 | 265 |
261 bool operator ==(other) => other is MalformedType; | 266 bool operator ==(other) => other is MalformedType; |
262 | 267 |
263 String toString() => name.slowToString(); | 268 String toString() => name.slowToString(); |
264 } | 269 } |
265 | 270 |
266 class InterfaceType extends DartType { | 271 class InterfaceType extends DartType { |
267 final Element element; | 272 final ClassElement element; |
268 final Link<DartType> typeArguments; | 273 final Link<DartType> typeArguments; |
269 | 274 |
270 InterfaceType(this.element, | 275 InterfaceType(this.element, |
271 [this.typeArguments = const Link<DartType>()]) { | 276 [this.typeArguments = const Link<DartType>()]) { |
272 assert(invariant(element, element.isDeclaration)); | 277 assert(invariant(element, element.isDeclaration)); |
273 } | 278 } |
274 | 279 |
275 TypeKind get kind => TypeKind.INTERFACE; | 280 TypeKind get kind => TypeKind.INTERFACE; |
276 | 281 |
277 SourceString get name => element.name; | 282 SourceString get name => element.name; |
(...skipping 15 matching lines...) Expand all Loading... |
293 return new InterfaceType(element, newTypeArguments); | 298 return new InterfaceType(element, newTypeArguments); |
294 } | 299 } |
295 return this; | 300 return this; |
296 } | 301 } |
297 | 302 |
298 DartType unalias(Compiler compiler) => this; | 303 DartType unalias(Compiler compiler) => this; |
299 | 304 |
300 String toString() { | 305 String toString() { |
301 StringBuffer sb = new StringBuffer(); | 306 StringBuffer sb = new StringBuffer(); |
302 sb.add(name.slowToString()); | 307 sb.add(name.slowToString()); |
303 if (!typeArguments.isEmpty) { | 308 if (!isRaw) { |
304 sb.add('<'); | 309 sb.add('<'); |
305 typeArguments.printOn(sb, ', '); | 310 typeArguments.printOn(sb, ', '); |
306 sb.add('>'); | 311 sb.add('>'); |
307 } | 312 } |
308 return sb.toString(); | 313 return sb.toString(); |
309 } | 314 } |
310 | 315 |
311 int get hashCode { | 316 int get hashCode { |
312 int hash = element.hashCode; | 317 int hash = element.hashCode; |
313 for (Link<DartType> arguments = this.typeArguments; | 318 for (Link<DartType> arguments = this.typeArguments; |
314 !arguments.isEmpty; | 319 !arguments.isEmpty; |
315 arguments = arguments.tail) { | 320 arguments = arguments.tail) { |
316 int argumentHash = arguments.head != null ? arguments.head.hashCode : 0; | 321 int argumentHash = arguments.head != null ? arguments.head.hashCode : 0; |
317 hash = 17 * hash + 3 * argumentHash; | 322 hash = 17 * hash + 3 * argumentHash; |
318 } | 323 } |
319 return hash; | 324 return hash; |
320 } | 325 } |
321 | 326 |
322 bool operator ==(other) { | 327 bool operator ==(other) { |
323 if (other is !InterfaceType) return false; | 328 if (other is !InterfaceType) return false; |
324 if (!identical(element, other.element)) return false; | 329 if (!identical(element, other.element)) return false; |
325 return typeArguments == other.typeArguments; | 330 return typeArguments == other.typeArguments; |
326 } | 331 } |
327 | 332 |
328 InterfaceType asRaw() { | 333 bool get isRaw => typeArguments.isEmpty || identical(this, element.rawType); |
329 if (typeArguments.isEmpty) return this; | 334 |
330 return new InterfaceType(element); | 335 InterfaceType asRaw() => element.rawType; |
331 } | |
332 } | 336 } |
333 | 337 |
334 class FunctionType extends DartType { | 338 class FunctionType extends DartType { |
335 final Element element; | 339 final Element element; |
336 DartType returnType; | 340 DartType returnType; |
337 Link<DartType> parameterTypes; | 341 Link<DartType> parameterTypes; |
338 | 342 |
339 FunctionType(DartType this.returnType, Link<DartType> this.parameterTypes, | 343 FunctionType(DartType this.returnType, Link<DartType> this.parameterTypes, |
340 Element this.element) { | 344 Element this.element) { |
341 assert(element == null || invariant(element, element.isDeclaration)); | 345 assert(element == null || invariant(element, element.isDeclaration)); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 DartType unalias(Compiler compiler) { | 442 DartType unalias(Compiler compiler) { |
439 // TODO(ahe): This should be [ensureResolved]. | 443 // TODO(ahe): This should be [ensureResolved]. |
440 compiler.resolveTypedef(element); | 444 compiler.resolveTypedef(element); |
441 // TODO(johnniwinther): Perform substitution on the unaliased type. | 445 // TODO(johnniwinther): Perform substitution on the unaliased type. |
442 return element.alias.unalias(compiler); | 446 return element.alias.unalias(compiler); |
443 } | 447 } |
444 | 448 |
445 String toString() { | 449 String toString() { |
446 StringBuffer sb = new StringBuffer(); | 450 StringBuffer sb = new StringBuffer(); |
447 sb.add(name.slowToString()); | 451 sb.add(name.slowToString()); |
448 if (!typeArguments.isEmpty) { | 452 if (!isRaw) { |
449 sb.add('<'); | 453 sb.add('<'); |
450 typeArguments.printOn(sb, ', '); | 454 typeArguments.printOn(sb, ', '); |
451 sb.add('>'); | 455 sb.add('>'); |
452 } | 456 } |
453 return sb.toString(); | 457 return sb.toString(); |
454 } | 458 } |
455 | 459 |
456 int get hashCode => 17 * element.hashCode; | 460 int get hashCode => 17 * element.hashCode; |
457 | 461 |
458 bool operator ==(other) { | 462 bool operator ==(other) { |
459 if (other is !TypedefType) return false; | 463 if (other is !TypedefType) return false; |
460 if (!identical(element, other.element)) return false; | 464 if (!identical(element, other.element)) return false; |
461 return typeArguments == other.typeArguments; | 465 return typeArguments == other.typeArguments; |
462 } | 466 } |
| 467 |
| 468 bool get isRaw => typeArguments.isEmpty || identical(this, element.rawType); |
| 469 |
| 470 TypedefType asRaw() => element.rawType; |
463 } | 471 } |
464 | 472 |
465 /** | 473 /** |
466 * Special type to hold the [dynamic] type. Used for correctly returning | 474 * Special type to hold the [dynamic] type. Used for correctly returning |
467 * 'dynamic' on [toString]. | 475 * 'dynamic' on [toString]. |
468 */ | 476 */ |
469 class DynamicType extends InterfaceType { | 477 class DynamicType extends InterfaceType { |
470 DynamicType(ClassElement element) : super(element); | 478 DynamicType(ClassElement element) : super(element); |
471 | 479 |
472 String toString() => 'dynamic'; | 480 String toString() => 'dynamic'; |
473 } | 481 } |
474 | 482 |
475 | 483 |
476 class Types { | 484 class Types { |
477 final Compiler compiler; | 485 final Compiler compiler; |
478 // TODO(karlklose): should we have a class Void? | 486 // TODO(karlklose): should we have a class Void? |
479 final VoidType voidType; | 487 final VoidType voidType; |
480 final InterfaceType dynamicType; | 488 final DynamicType dynamicType; |
481 | 489 |
482 Types(Compiler compiler, ClassElement dynamicElement) | 490 Types(Compiler compiler, ClassElement dynamicElement) |
483 : this.with(compiler, dynamicElement, | 491 : this.with(compiler, dynamicElement, |
484 new LibraryElement(new Script(null, null))); | 492 new LibraryElement(new Script(null, null))); |
485 | 493 |
486 Types.with(Compiler this.compiler, | 494 Types.with(Compiler this.compiler, |
487 ClassElement dynamicElement, | 495 ClassElement dynamicElement, |
488 LibraryElement library) | 496 LibraryElement library) |
489 : voidType = new VoidType(new VoidElement(library)), | 497 : voidType = new VoidType(new VoidElement(library)), |
490 dynamicType = new DynamicType(dynamicElement) { | 498 dynamicType = new DynamicType(dynamicElement) { |
491 dynamicElement.type = dynamicType; | 499 dynamicElement.rawType = dynamicElement.thisType = dynamicType; |
492 } | 500 } |
493 | 501 |
494 /** Returns true if t is a subtype of s */ | 502 /** Returns true if t is a subtype of s */ |
495 bool isSubtype(DartType t, DartType s) { | 503 bool isSubtype(DartType t, DartType s) { |
496 if (identical(t, s) || | 504 if (identical(t, s) || |
497 identical(t, dynamicType) || | 505 identical(t, dynamicType) || |
498 identical(s, dynamicType) || | 506 identical(s, dynamicType) || |
499 identical(s.element, compiler.objectClass) || | 507 identical(s.element, compiler.objectClass) || |
500 identical(t.element, compiler.nullClass)) { | 508 identical(t.element, compiler.nullClass)) { |
501 return true; | 509 return true; |
502 } | 510 } |
503 t = t.unalias(compiler); | 511 t = t.unalias(compiler); |
504 s = s.unalias(compiler); | 512 s = s.unalias(compiler); |
505 | 513 |
506 if (t is VoidType) { | 514 if (t is VoidType) { |
507 return false; | 515 return false; |
508 } else if (t is MalformedType) { | 516 } else if (t is MalformedType || s is MalformedType) { |
| 517 // TODO(johnniwinther): Malformed types should be treated as dynamic and |
| 518 // thus return true here. |
509 return false; | 519 return false; |
510 } else if (t is InterfaceType) { | 520 } else if (t is InterfaceType) { |
511 if (s is !InterfaceType) return false; | 521 if (s is !InterfaceType) return false; |
512 ClassElement tc = t.element; | 522 ClassElement tc = t.element; |
513 if (identical(tc, s.element)) return true; | 523 if (identical(tc, s.element)) return true; |
514 for (Link<DartType> supertypes = tc.allSupertypes; | 524 for (Link<DartType> supertypes = tc.allSupertypes; |
515 supertypes != null && !supertypes.isEmpty; | 525 supertypes != null && !supertypes.isEmpty; |
516 supertypes = supertypes.tail) { | 526 supertypes = supertypes.tail) { |
517 DartType supertype = supertypes.head; | 527 DartType supertype = supertypes.head; |
518 if (identical(supertype.element, s.element)) return true; | 528 if (identical(supertype.element, s.element)) return true; |
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 } | 1228 } |
1219 | 1229 |
1220 DartType visitStringNode(StringNode node) { | 1230 DartType visitStringNode(StringNode node) { |
1221 compiler.unimplemented('visitNode', node: node); | 1231 compiler.unimplemented('visitNode', node: node); |
1222 } | 1232 } |
1223 | 1233 |
1224 DartType visitLibraryDependency(LibraryDependency node) { | 1234 DartType visitLibraryDependency(LibraryDependency node) { |
1225 compiler.unimplemented('visitNode', node: node); | 1235 compiler.unimplemented('visitNode', node: node); |
1226 } | 1236 } |
1227 } | 1237 } |
OLD | NEW |