| 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 15 matching lines...) Expand all Loading... |
| 26 | 26 |
| 27 interface Type { | 27 interface Type { |
| 28 SourceString get name(); | 28 SourceString get name(); |
| 29 Element get element(); | 29 Element get element(); |
| 30 } | 30 } |
| 31 | 31 |
| 32 class TypeVariableType implements Type { | 32 class TypeVariableType implements Type { |
| 33 final SourceString name; | 33 final SourceString name; |
| 34 Element element; | 34 Element element; |
| 35 TypeVariableType(this.name, [this.element]); | 35 TypeVariableType(this.name, [this.element]); |
| 36 | |
| 37 toString() => name.toString(); | |
| 38 } | 36 } |
| 39 | 37 |
| 40 /** | 38 /** |
| 41 * A statement type tracks whether a statement returns or may return. | 39 * A statement type tracks whether a statement returns or may return. |
| 42 */ | 40 */ |
| 43 class StatementType implements Type { | 41 class StatementType implements Type { |
| 44 final String stringName; | 42 final String stringName; |
| 45 Element get element() => null; | 43 Element get element() => null; |
| 46 | 44 |
| 47 SourceString get name() => new SourceString(stringName); | 45 SourceString get name() => new SourceString(stringName); |
| 48 | 46 |
| 49 const StatementType(this.stringName); | 47 const StatementType(this.stringName); |
| 50 | 48 |
| 51 static final RETURNING = const StatementType('<returning>'); | 49 static final RETURNING = const StatementType('<returning>'); |
| 52 static final NOT_RETURNING = const StatementType('<not returning>'); | 50 static final NOT_RETURNING = const StatementType('<not returning>'); |
| 53 static final MAYBE_RETURNING = const StatementType('<maybe returning>'); | 51 static final MAYBE_RETURNING = const StatementType('<maybe returning>'); |
| 54 | 52 |
| 55 /** Combine the information about two control-flow edges that are joined. */ | 53 /** Combine the information about two control-flow edges that are joined. */ |
| 56 StatementType join(StatementType other) { | 54 StatementType join(StatementType other) { |
| 57 return (this === other) ? this : MAYBE_RETURNING; | 55 return (this === other) ? this : MAYBE_RETURNING; |
| 58 } | 56 } |
| 59 | 57 |
| 60 String toString() => stringName; | 58 String toString() => stringName; |
| 61 } | 59 } |
| 62 | 60 |
| 63 class InterfaceType implements Type { | 61 class SimpleType implements Type { |
| 64 final SourceString name; | 62 final SourceString name; |
| 65 final ClassElement element; | 63 final Element element; |
| 66 final Link<Type> arguments; | |
| 67 | 64 |
| 68 const InterfaceType(this.name, this.element, this.arguments); | 65 const SimpleType(SourceString this.name, Element this.element); |
| 69 | 66 |
| 70 toString() { | |
| 71 StringBuffer sb = new StringBuffer(); | |
| 72 sb.add(name.slowToString()); | |
| 73 if (!arguments.isEmpty()) { | |
| 74 sb.add('<'); | |
| 75 arguments.printOn(sb, ', '); | |
| 76 sb.add('>'); | |
| 77 } | |
| 78 return sb.toString(); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 // TODO(karlklose): merge into InterfaceType as a named constructor. | |
| 83 class SimpleType extends InterfaceType { | |
| 84 const SimpleType(SourceString name, Element element) | |
| 85 : super(name, element, const EmptyLink<Type>()); | |
| 86 String toString() => name.slowToString(); | 67 String toString() => name.slowToString(); |
| 87 } | 68 } |
| 88 | 69 |
| 89 class FunctionType implements Type { | 70 class FunctionType implements Type { |
| 90 final Element element; | 71 final Element element; |
| 91 final Type returnType; | 72 final Type returnType; |
| 92 final Link<Type> parameterTypes; | 73 final Link<Type> parameterTypes; |
| 93 | 74 |
| 94 const FunctionType(Type this.returnType, Link<Type> this.parameterTypes, | 75 const FunctionType(Type this.returnType, Link<Type> this.parameterTypes, |
| 95 Element this.element); | 76 Element this.element); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 113 static final DYNAMIC = const SourceString('Dynamic'); | 94 static final DYNAMIC = const SourceString('Dynamic'); |
| 114 static final STRING = const SourceString('String'); | 95 static final STRING = const SourceString('String'); |
| 115 static final BOOL = const SourceString('bool'); | 96 static final BOOL = const SourceString('bool'); |
| 116 static final OBJECT = const SourceString('Object'); | 97 static final OBJECT = const SourceString('Object'); |
| 117 static final LIST = const SourceString('List'); | 98 static final LIST = const SourceString('List'); |
| 118 | 99 |
| 119 final SimpleType voidType; | 100 final SimpleType voidType; |
| 120 final SimpleType dynamicType; | 101 final SimpleType dynamicType; |
| 121 | 102 |
| 122 Types() : this.with(new LibraryElement(new Script(null, null))); | 103 Types() : this.with(new LibraryElement(new Script(null, null))); |
| 123 | |
| 124 Types.with(LibraryElement library) | 104 Types.with(LibraryElement library) |
| 125 : voidType = new SimpleType(VOID, new ClassElement(VOID, library)), | 105 : voidType = new SimpleType(VOID, new ClassElement(VOID, library)), |
| 126 dynamicType = new SimpleType(DYNAMIC, new ClassElement(DYNAMIC, library)); | 106 dynamicType = new SimpleType(DYNAMIC, new ClassElement(DYNAMIC, library)); |
| 127 | 107 |
| 128 Type lookup(SourceString s) { | 108 Type lookup(SourceString s) { |
| 129 if (VOID == s) { | 109 if (VOID == s) { |
| 130 return voidType; | 110 return voidType; |
| 131 } else if (DYNAMIC == s || s.stringValue === 'var') { | 111 } else if (DYNAMIC == s || s.stringValue === 'var') { |
| 132 return dynamicType; | 112 return dynamicType; |
| 133 } | 113 } |
| 134 return null; | 114 return null; |
| 135 } | 115 } |
| 136 | 116 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 Element element = compiler.coreLibrary.find(name); | 165 Element element = compiler.coreLibrary.find(name); |
| 186 if (element !== null && element.kind === ElementKind.CLASS) { | 166 if (element !== null && element.kind === ElementKind.CLASS) { |
| 187 return element.computeType(compiler); | 167 return element.computeType(compiler); |
| 188 } | 168 } |
| 189 return null; | 169 return null; |
| 190 } | 170 } |
| 191 | 171 |
| 192 class TypeCheckerVisitor implements Visitor<Type> { | 172 class TypeCheckerVisitor implements Visitor<Type> { |
| 193 final Compiler compiler; | 173 final Compiler compiler; |
| 194 final TreeElements elements; | 174 final TreeElements elements; |
| 175 Node lastSeenNode; |
| 195 final Types types; | 176 final Types types; |
| 196 | 177 |
| 197 Node lastSeenNode; | |
| 198 Type expectedReturnType; | 178 Type expectedReturnType; |
| 199 ClassElement currentClass; | 179 ClassElement currentClass; |
| 200 | 180 |
| 201 Type intType; | 181 Type intType; |
| 202 Type doubleType; | 182 Type doubleType; |
| 203 Type boolType; | 183 Type boolType; |
| 204 Type stringType; | 184 Type stringType; |
| 205 Type objectType; | 185 Type objectType; |
| 206 Type listType; | 186 Type listType; |
| 207 | 187 |
| 208 TypeCheckerVisitor(this.compiler, this.elements, this.types) { | 188 TypeCheckerVisitor(Compiler this.compiler, TreeElements this.elements, |
| 189 Types this.types) { |
| 209 intType = lookupType(Types.INT, compiler, types); | 190 intType = lookupType(Types.INT, compiler, types); |
| 210 doubleType = lookupType(Types.DOUBLE, compiler, types); | 191 doubleType = lookupType(Types.DOUBLE, compiler, types); |
| 211 boolType = lookupType(Types.BOOL, compiler, types); | 192 boolType = lookupType(Types.BOOL, compiler, types); |
| 212 stringType = lookupType(Types.STRING, compiler, types); | 193 stringType = lookupType(Types.STRING, compiler, types); |
| 213 objectType = lookupType(Types.OBJECT, compiler, types); | 194 objectType = lookupType(Types.OBJECT, compiler, types); |
| 214 listType = lookupType(Types.LIST, compiler, types); | 195 listType = lookupType(Types.LIST, compiler, types); |
| 215 } | 196 } |
| 216 | 197 |
| 217 Type fail(node, [reason]) { | 198 Type fail(node, [reason]) { |
| 218 String message = 'cannot type-check'; | 199 String message = 'cannot type-check'; |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 } else if (node.isPropertyAccess) { | 423 } else if (node.isPropertyAccess) { |
| 443 if (node.receiver !== null) fail(node, 'cannot handle fields'); | 424 if (node.receiver !== null) fail(node, 'cannot handle fields'); |
| 444 Element element = elements[node]; | 425 Element element = elements[node]; |
| 445 if (element === null) fail(node.selector, 'unresolved property'); | 426 if (element === null) fail(node.selector, 'unresolved property'); |
| 446 return computeType(element); | 427 return computeType(element); |
| 447 | 428 |
| 448 } else if (node.isFunctionObjectInvocation) { | 429 } else if (node.isFunctionObjectInvocation) { |
| 449 fail(node.receiver, 'function object invocation unimplemented'); | 430 fail(node.receiver, 'function object invocation unimplemented'); |
| 450 | 431 |
| 451 } else { | 432 } else { |
| 452 Type computeFunType() { | 433 FunctionType computeFunType() { |
| 453 if (node.receiver !== null) { | 434 if (node.receiver !== null) { |
| 454 Type receiverType = analyze(node.receiver); | 435 Type receiverType = analyze(node.receiver); |
| 455 if (receiverType === null) { | 436 if (receiverType === types.dynamicType) return null; |
| 456 fail(node.receiver, 'receivertype is null'); | 437 if (receiverType === null) { |
| 457 } | 438 fail(node.receiver, 'receivertype is null'); |
| 458 if (receiverType.element.kind !== ElementKind.CLASS) { | 439 } |
| 459 fail(node.receiver, 'receivertype is not a class'); | 440 if (receiverType.element.kind !== ElementKind.CLASS) { |
| 460 } | 441 fail(node.receiver, 'receivertype is not a class'); |
| 461 ClassElement classElement = receiverType.element; | 442 } |
| 462 // TODO(karlklose): substitute type arguments. | 443 ClassElement classElement = receiverType.element; |
| 463 if (classElement === compiler.dynamicClass) return null; | 444 // TODO(karlklose): substitute type arguments. |
| 464 Type memberType = | 445 Type memberType = |
| 465 lookupMethodType(selector, classElement, selector.source); | 446 lookupMethodType(selector, classElement, selector.source); |
| 466 if (memberType.element === compiler.dynamicClass) return null; | 447 if (memberType === types.dynamicType) return null; |
| 467 return memberType; | 448 return memberType; |
| 468 } else { | 449 } else { |
| 469 Element element = elements[node]; | 450 Element element = elements[node]; |
| 470 if (element === null) { | 451 if (element === null) { |
| 471 fail(node, 'unresolved ${node.selector}'); | 452 fail(node, 'unresolved ${node.selector}'); |
| 472 } else if (element.kind === ElementKind.FUNCTION) { | 453 } else if (element.kind === ElementKind.FUNCTION) { |
| 473 return computeType(element); | 454 return computeType(element); |
| 474 } else if (element.kind === ElementKind.FOREIGN) { | 455 } else if (element.kind === ElementKind.FOREIGN) { |
| 475 return null; | 456 return null; |
| 476 } else { | 457 } else { |
| 477 fail(node, 'unexpected element kind ${element.kind}'); | 458 fail(node, 'unexpected element kind ${element.kind}'); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 } | 707 } |
| 727 | 708 |
| 728 visitCatchBlock(CatchBlock node) { | 709 visitCatchBlock(CatchBlock node) { |
| 729 fail(node); | 710 fail(node); |
| 730 } | 711 } |
| 731 | 712 |
| 732 visitTypedef(Typedef node) { | 713 visitTypedef(Typedef node) { |
| 733 fail(node); | 714 fail(node); |
| 734 } | 715 } |
| 735 } | 716 } |
| OLD | NEW |