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

Side by Side Diff: lib/compiler/implementation/typechecker.dart

Issue 10091037: Clean up handling of types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove debug code. Created 8 years, 8 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 | « lib/compiler/implementation/resolver.dart ('k') | tests/utils/src/DummyCompilerTest.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 static final DOUBLE = const SourceString('double'); 112 static final DOUBLE = const SourceString('double');
113 static final DYNAMIC = const SourceString('Dynamic'); 113 static final DYNAMIC = const SourceString('Dynamic');
114 static final STRING = const SourceString('String'); 114 static final STRING = const SourceString('String');
115 static final BOOL = const SourceString('bool'); 115 static final BOOL = const SourceString('bool');
116 static final OBJECT = const SourceString('Object'); 116 static final OBJECT = const SourceString('Object');
117 static final LIST = const SourceString('List'); 117 static final LIST = const SourceString('List');
118 118
119 final SimpleType voidType; 119 final SimpleType voidType;
120 final SimpleType dynamicType; 120 final SimpleType dynamicType;
121 121
122 Types() : this.with(new LibraryElement(new Script(null, null))); 122 Types(Element dynamicElement)
123 : this.with(dynamicElement, new LibraryElement(new Script(null, null)));
123 124
124 Types.with(LibraryElement library) 125 Types.with(Element dynamicElement, LibraryElement library)
125 : voidType = new SimpleType(VOID, new ClassElement(VOID, library)), 126 : voidType = new SimpleType(VOID, new ClassElement(VOID, library)),
ahe 2012/04/17 16:14:47 Perhaps we should have a Void class as well.
karlklose 2012/04/18 08:19:08 I am not sure, I added a TODO for now.
ahe 2012/04/18 08:49:04 Good plan.
126 dynamicType = new SimpleType(DYNAMIC, new ClassElement(DYNAMIC, library)); 127 dynamicType = new SimpleType(DYNAMIC, dynamicElement);
127 128
128 Type lookup(SourceString s) { 129 Type lookup(SourceString s) {
129 if (VOID == s) { 130 if (VOID == s) {
130 return voidType; 131 return voidType;
131 } else if (DYNAMIC == s || s.stringValue === 'var') { 132 } else if (DYNAMIC == s || s.stringValue === 'var') {
132 return dynamicType; 133 return dynamicType;
133 } 134 }
134 return null; 135 return null;
135 } 136 }
136 137
137 /** Returns true if t is a subtype of s */ 138 /** Returns true if t is a subtype of s */
138 bool isSubtype(Type t, Type s) { 139 bool isSubtype(Type t, Type s) {
139 if (t === s || t === dynamicType || s === dynamicType || 140 if (t === s || t === dynamicType || s === dynamicType ||
140 s.name == OBJECT) return true; 141 s.name == OBJECT) return true;
141 if (t is SimpleType) { 142 if (t is InterfaceType) {
142 if (s is !SimpleType) return false; 143 if (s is !InterfaceType) return false;
143 ClassElement tc = t.element; 144 ClassElement tc = t.element;
145 if (tc === s.element) return true;
144 for (Link<Type> supertypes = tc.allSupertypes; 146 for (Link<Type> supertypes = tc.allSupertypes;
145 supertypes != null && !supertypes.isEmpty(); 147 supertypes != null && !supertypes.isEmpty();
146 supertypes = supertypes.tail) { 148 supertypes = supertypes.tail) {
147 Type supertype = supertypes.head; 149 Type supertype = supertypes.head;
148 if (supertype.element === s.element) return true; 150 if (supertype.element === s.element) return true;
149 } 151 }
150 return false; 152 return false;
151 } else if (t is FunctionType) { 153 } else if (t is FunctionType) {
152 if (s is !FunctionType) return false; 154 if (s is !FunctionType) return false;
153 FunctionType tf = t; 155 FunctionType tf = t;
154 FunctionType sf = s; 156 FunctionType sf = s;
155 Link<Type> tps = tf.parameterTypes; 157 Link<Type> tps = tf.parameterTypes;
156 Link<Type> sps = sf.parameterTypes; 158 Link<Type> sps = sf.parameterTypes;
157 while (!tps.isEmpty() && !sps.isEmpty()) { 159 while (!tps.isEmpty() && !sps.isEmpty()) {
158 if (!isAssignable(tps.head, sps.head)) return false; 160 if (!isAssignable(tps.head, sps.head)) return false;
159 tps = tps.tail; 161 tps = tps.tail;
160 sps = sps.tail; 162 sps = sps.tail;
161 } 163 }
162 if (!tps.isEmpty() || !sps.isEmpty()) return false; 164 if (!tps.isEmpty() || !sps.isEmpty()) return false;
163 if (!isAssignable(sf.returnType, tf.returnType)) return false; 165 if (!isAssignable(sf.returnType, tf.returnType)) return false;
164 return true; 166 return true;
167 } else if (t is TypeVariableType) {
168 if (s is !TypeVariableType) return false;
169 return (t.element === s.element);
165 } else { 170 } else {
166 throw 'internal error: unknown type kind'; 171 throw 'internal error: unknown type kind';
167 } 172 }
168 } 173 }
169 174
170 bool isAssignable(Type r, Type s) { 175 bool isAssignable(Type r, Type s) {
171 return isSubtype(r, s) || isSubtype(s, r); 176 return isSubtype(r, s) || isSubtype(s, r);
172 } 177 }
173 } 178 }
174 179
175 class CancelTypeCheckException { 180 class CancelTypeCheckException {
176 final Node node; 181 final Node node;
177 final String reason; 182 final String reason;
178 183
179 CancelTypeCheckException(this.node, this.reason); 184 CancelTypeCheckException(this.node, this.reason);
180 } 185 }
181 186
182 Type lookupType(SourceString name, Compiler compiler, types) {
183 Type t = types.lookup(name);
184 if (t !== null) return t;
185 Element element = compiler.coreLibrary.find(name);
186 if (element !== null && element.kind === ElementKind.CLASS) {
187 return element.computeType(compiler);
188 }
189 return null;
190 }
191
192 class TypeCheckerVisitor implements Visitor<Type> { 187 class TypeCheckerVisitor implements Visitor<Type> {
193 final Compiler compiler; 188 final Compiler compiler;
194 final TreeElements elements; 189 final TreeElements elements;
195 final Types types; 190 final Types types;
196 191
197 Node lastSeenNode; 192 Node lastSeenNode;
198 Type expectedReturnType; 193 Type expectedReturnType;
199 ClassElement currentClass; 194 ClassElement currentClass;
200 195
201 Link<Type> cascadeTypes = const EmptyLink<Type>(); 196 Link<Type> cascadeTypes = const EmptyLink<Type>();
202 197
203 Type intType; 198 Type intType;
204 Type doubleType; 199 Type doubleType;
205 Type boolType; 200 Type boolType;
206 Type stringType; 201 Type stringType;
207 Type objectType; 202 Type objectType;
208 Type listType; 203 Type listType;
209 204
210 TypeCheckerVisitor(this.compiler, this.elements, this.types) { 205 TypeCheckerVisitor(this.compiler, this.elements, this.types) {
211 intType = lookupType(Types.INT, compiler, types); 206 intType = compiler.intClass.computeType(compiler);
212 doubleType = lookupType(Types.DOUBLE, compiler, types); 207 doubleType = compiler.doubleClass.computeType(compiler);
213 boolType = lookupType(Types.BOOL, compiler, types); 208 boolType = compiler.boolClass.computeType(compiler);
214 stringType = lookupType(Types.STRING, compiler, types); 209 stringType = compiler.stringClass.computeType(compiler);
215 objectType = lookupType(Types.OBJECT, compiler, types); 210 objectType = compiler.objectClass.computeType(compiler);
216 listType = lookupType(Types.LIST, compiler, types); 211 listType = compiler.listClass.computeType(compiler);
217 } 212 }
218 213
219 Type fail(node, [reason]) { 214 Type fail(node, [reason]) {
220 String message = 'cannot type-check'; 215 String message = 'cannot type-check';
221 if (reason !== null) { 216 if (reason !== null) {
222 message = '$message: $reason'; 217 message = '$message: $reason';
223 } 218 }
224 throw new CancelTypeCheckException(node, message); 219 throw new CancelTypeCheckException(node, message);
225 } 220 }
226 221
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 return StatementType.RETURNING; 613 return StatementType.RETURNING;
619 } 614 }
620 615
621 Type computeType(Element element) { 616 Type computeType(Element element) {
622 if (element === null) return types.dynamicType; 617 if (element === null) return types.dynamicType;
623 Type result = element.computeType(compiler); 618 Type result = element.computeType(compiler);
624 return (result !== null) ? result : types.dynamicType; 619 return (result !== null) ? result : types.dynamicType;
625 } 620 }
626 621
627 Type visitTypeAnnotation(TypeAnnotation node) { 622 Type visitTypeAnnotation(TypeAnnotation node) {
628 if (node.typeName === null) return types.dynamicType; 623 return elements.getType(node);
629 Identifier identifier = node.typeName.asIdentifier();
630 if (identifier === null) {
631 fail(node.typeName, 'library prefix not implemented');
632 }
633 // TODO(ahe): Why wasn't this resolved by the resolver?
634 Type type = lookupType(identifier.source, compiler, types);
635 if (type === null) {
636 // The type name cannot be resolved, but the resolver
637 // already gave a warning, so we continue checking.
638 return types.dynamicType;
639 }
640 return type;
641 } 624 }
642 625
643 visitTypeVariable(TypeVariable node) { 626 visitTypeVariable(TypeVariable node) {
644 return types.dynamicType; 627 return types.dynamicType;
645 } 628 }
646 629
647 Type visitVariableDefinitions(VariableDefinitions node) { 630 Type visitVariableDefinitions(VariableDefinitions node) {
648 Type type = analyzeWithDefault(node.type, types.dynamicType); 631 Type type = analyzeWithDefault(node.type, types.dynamicType);
649 if (type == types.voidType) { 632 if (type == types.voidType) {
650 reportTypeWarning(node.type, MessageKind.VOID_VARIABLE); 633 reportTypeWarning(node.type, MessageKind.VOID_VARIABLE);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 } 732 }
750 733
751 visitCatchBlock(CatchBlock node) { 734 visitCatchBlock(CatchBlock node) {
752 fail(node); 735 fail(node);
753 } 736 }
754 737
755 visitTypedef(Typedef node) { 738 visitTypedef(Typedef node) {
756 fail(node); 739 fail(node);
757 } 740 }
758 } 741 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/resolver.dart ('k') | tests/utils/src/DummyCompilerTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698