Chromium Code Reviews| 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 class TypeCheckerTask extends CompilerTask { | 5 class TypeCheckerTask extends CompilerTask { |
| 6 TypeCheckerTask(Compiler compiler) : super(compiler); | 6 TypeCheckerTask(Compiler compiler) : super(compiler); |
| 7 String get name() => "Type checker"; | 7 String get name() => "Type checker"; |
| 8 | 8 |
| 9 static final bool LOG_FAILURES = false; | 9 static final bool LOG_FAILURES = false; |
| 10 | 10 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 static final MAYBE_RETURNING = const StatementType('<maybe returning>'); | 53 static final MAYBE_RETURNING = const StatementType('<maybe returning>'); |
| 54 | 54 |
| 55 /** Combine the information about two control-flow edges that are joined. */ | 55 /** Combine the information about two control-flow edges that are joined. */ |
| 56 StatementType join(StatementType other) { | 56 StatementType join(StatementType other) { |
| 57 return (this === other) ? this : MAYBE_RETURNING; | 57 return (this === other) ? this : MAYBE_RETURNING; |
| 58 } | 58 } |
| 59 | 59 |
| 60 String toString() => stringName; | 60 String toString() => stringName; |
| 61 } | 61 } |
| 62 | 62 |
| 63 class VoidType implements Type { | |
| 64 const VoidType(this.element); | |
| 65 SourceString get name() => Types.VOID; | |
| 66 final VoidElement element; | |
| 67 } | |
| 68 | |
| 63 class InterfaceType implements Type { | 69 class InterfaceType implements Type { |
| 64 final Element element; | 70 final Element element; |
| 65 final Link<Type> arguments; | 71 final Link<Type> arguments; |
| 66 | 72 |
| 67 const InterfaceType(this.element, | 73 const InterfaceType(this.element, |
| 68 [this.arguments = const EmptyLink<Type>()]); | 74 [this.arguments = const EmptyLink<Type>()]); |
| 69 | 75 |
| 70 SourceString get name() => element.name; | 76 SourceString get name() => element.name; |
| 71 | 77 |
| 72 toString() { | 78 toString() { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 class Types { | 110 class Types { |
| 105 static final VOID = const SourceString('void'); | 111 static final VOID = const SourceString('void'); |
| 106 static final INT = const SourceString('int'); | 112 static final INT = const SourceString('int'); |
| 107 static final DOUBLE = const SourceString('double'); | 113 static final DOUBLE = const SourceString('double'); |
| 108 static final DYNAMIC = const SourceString('Dynamic'); | 114 static final DYNAMIC = const SourceString('Dynamic'); |
| 109 static final STRING = const SourceString('String'); | 115 static final STRING = const SourceString('String'); |
| 110 static final BOOL = const SourceString('bool'); | 116 static final BOOL = const SourceString('bool'); |
| 111 static final OBJECT = const SourceString('Object'); | 117 static final OBJECT = const SourceString('Object'); |
| 112 static final LIST = const SourceString('List'); | 118 static final LIST = const SourceString('List'); |
| 113 | 119 |
| 114 final InterfaceType voidType; | 120 final VoidType voidType; |
| 115 final InterfaceType dynamicType; | 121 final InterfaceType dynamicType; |
| 116 | 122 |
| 117 Types(Element dynamicElement) | 123 Types(Element dynamicElement) |
| 118 : this.with(dynamicElement, new LibraryElement(new Script(null, null))); | 124 : this.with(dynamicElement, new LibraryElement(new Script(null, null))); |
| 119 | 125 |
| 120 // TODO(karlklose): should we have a class Void? | 126 // TODO(karlklose): should we have a class Void? |
| 121 Types.with(Element dynamicElement, LibraryElement library) | 127 Types.with(Element dynamicElement, LibraryElement library) |
| 122 : voidType = new InterfaceType(new ClassElement(VOID, library)), | 128 : voidType = new VoidType(new VoidElement(library)), |
| 123 dynamicType = new InterfaceType(dynamicElement); | 129 dynamicType = new InterfaceType(dynamicElement); |
| 124 | 130 |
| 125 Type lookup(SourceString s) { | 131 Type lookup(SourceString s) { |
| 126 if (VOID == s) { | 132 if (VOID == s) { |
| 127 return voidType; | 133 return voidType; |
| 128 } else if (DYNAMIC == s || s.stringValue === 'var') { | 134 } else if (DYNAMIC == s || s.stringValue === 'var') { |
| 129 return dynamicType; | 135 return dynamicType; |
| 130 } | 136 } |
| 131 return null; | 137 return null; |
| 132 } | 138 } |
| 133 | 139 |
| 134 /** Returns true if t is a subtype of s */ | 140 /** Returns true if t is a subtype of s */ |
| 135 bool isSubtype(Type t, Type s) { | 141 bool isSubtype(Type t, Type s) { |
| 136 if (t === s || t === dynamicType || s === dynamicType || | 142 if (t === s || t === dynamicType || s === dynamicType || |
| 137 s.name == OBJECT) return true; | 143 s.name == OBJECT) return true; |
| 138 if (t is InterfaceType) { | 144 if (t is VoidType) { |
| 145 return false; | |
| 146 } else if (t is InterfaceType) { | |
| 139 if (s is !InterfaceType) return false; | 147 if (s is !InterfaceType) return false; |
| 140 ClassElement tc = t.element; | 148 ClassElement tc = t.element; |
| 141 if (tc === s.element) return true; | 149 if (tc === s.element) return true; |
| 142 for (Link<Type> supertypes = tc.allSupertypes; | 150 for (Link<Type> supertypes = tc.allSupertypes; |
| 143 supertypes != null && !supertypes.isEmpty(); | 151 supertypes != null && !supertypes.isEmpty(); |
| 144 supertypes = supertypes.tail) { | 152 supertypes = supertypes.tail) { |
| 145 Type supertype = supertypes.head; | 153 Type supertype = supertypes.head; |
| 146 if (supertype.element === s.element) return true; | 154 if (supertype.element === s.element) return true; |
| 147 } | 155 } |
| 148 return false; | 156 return false; |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 return type; | 579 return type; |
| 572 } | 580 } |
| 573 | 581 |
| 574 Type visitOperator(Operator node) { | 582 Type visitOperator(Operator node) { |
| 575 fail(node, 'internal error'); | 583 fail(node, 'internal error'); |
| 576 } | 584 } |
| 577 | 585 |
| 578 /** Dart Programming Language Specification: 11.10 Return */ | 586 /** Dart Programming Language Specification: 11.10 Return */ |
| 579 Type visitReturn(Return node) { | 587 Type visitReturn(Return node) { |
| 580 final expression = node.expression; | 588 final expression = node.expression; |
| 581 final isVoidFunction = | 589 final isVoidFunction = (expectedReturnType === types.voidType); |
| 582 (expectedReturnType.element === compiler.types.voidType.element); | |
| 583 | 590 |
| 584 // Executing a return statement return e; [...] It is a static type warning | 591 // Executing a return statement return e; [...] It is a static type warning |
| 585 // if the type of e may not be assigned to the declared return type of the | 592 // if the type of e may not be assigned to the declared return type of the |
| 586 // immediately enclosing function. | 593 // immediately enclosing function. |
| 587 if (expression !== null) { | 594 if (expression !== null) { |
| 588 final expressionType = analyze(expression); | 595 final expressionType = analyze(expression); |
| 589 if (isVoidFunction | 596 if (isVoidFunction && |
| 590 && !types.isAssignable(expressionType, types.voidType)) { | 597 !types.isAssignable(expressionType, types.voidType)) { |
|
ngeoffray
2012/05/09 08:54:40
Why this change? I think we followed Java's style
karlklose
2012/05/09 10:32:41
We certainly do not follow it everywhere in our co
| |
| 591 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID, | 598 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID, |
| 592 [expressionType]); | 599 [expressionType]); |
| 593 } else { | 600 } else { |
| 594 checkAssignable(expression, expectedReturnType, expressionType); | 601 checkAssignable(expression, expectedReturnType, expressionType); |
| 595 } | 602 } |
| 596 | 603 |
| 597 // Let f be the function immediately enclosing a return statement of the | 604 // Let f be the function immediately enclosing a return statement of the |
| 598 // form 'return;' It is a static warning if both of the following conditions | 605 // form 'return;' It is a static warning if both of the following conditions |
| 599 // hold: | 606 // hold: |
| 600 // - f is not a generative constructor. | 607 // - f is not a generative constructor. |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 729 } | 736 } |
| 730 | 737 |
| 731 visitCatchBlock(CatchBlock node) { | 738 visitCatchBlock(CatchBlock node) { |
| 732 fail(node); | 739 fail(node); |
| 733 } | 740 } |
| 734 | 741 |
| 735 visitTypedef(Typedef node) { | 742 visitTypedef(Typedef node) { |
| 736 fail(node); | 743 fail(node); |
| 737 } | 744 } |
| 738 } | 745 } |
| OLD | NEW |