| 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 |
| 11 void check(Node tree, TreeElements elements) { | 11 void check(Node tree, TreeElements elements) { |
| 12 measure(() { | 12 measure(() { |
| 13 Visitor visitor = | 13 Visitor visitor = |
| 14 new TypeCheckerVisitor(compiler, elements, compiler.types); | 14 new TypeCheckerVisitor(compiler, elements, compiler.types); |
| 15 try { | 15 try { |
| 16 tree.accept(visitor); | 16 tree.accept(visitor); |
| 17 } catch (CancelTypeCheckException e) { | 17 } catch (CancelTypeCheckException e) { |
| 18 if (LOG_FAILURES) { | 18 if (LOG_FAILURES) { |
| 19 // Do not warn about unimplemented features; log message instead. | 19 // Do not warn about unimplemented features; log message instead. |
| 20 compiler.log("'${e.node}': ${e.reason}"); | 20 compiler.log("'${e.node}': ${e.reason}"); |
| 21 } | 21 } |
| 22 } | 22 } |
| 23 }); | 23 }); |
| 24 } | 24 } |
| 25 } | 25 } |
| 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 |
| 31 /** |
| 32 * Performs the substitution [arguments[i]/parameters[i]]this. |
| 33 * The notation is known from this lambda calculus rule: |
| 34 * (lambda x.e0)e1 -> [e1/x]e0. |
| 35 * |
| 36 * See [TypeVariableType] for a motivation for this method. |
| 37 */ |
| 38 Type subst(Link<Type> arguments, List<Type> parameters); |
| 30 } | 39 } |
| 31 | 40 |
| 41 /** |
| 42 * Represents a type variable, that is the type parameters of a class |
| 43 * or interface type. For example, in class Array<E> { ... }`, |
| 44 * E is a type variable. |
| 45 * |
| 46 * Each class/interface should have its own unique type variables, |
| 47 * one for each type parameter. A class/interface with type parameters |
| 48 * is said to be parameterized or generic. |
| 49 * |
| 50 * Non-static members, constructors, and factories of generic |
| 51 * class/interface can refer to type variables of the current class |
| 52 * (not of supertypes). |
| 53 * |
| 54 * When using a generic type, also known as an application or |
| 55 * instantiation of the type, the actual type arguments should be |
| 56 * substituted for the type variables in the class declaration. |
| 57 * |
| 58 * For example, given a box, `class Box<T> { T value; }`, the |
| 59 * type of the expression `new Box<String>().value` is |
| 60 * [String] because we must substitute `String` for the |
| 61 * the type variable `T`. |
| 62 */ |
| 32 class TypeVariableType implements Type { | 63 class TypeVariableType implements Type { |
| 33 final SourceString name; | 64 final SourceString name; |
| 34 TypeVariableElement element; | 65 TypeVariableElement element; |
| 35 TypeVariableType(this.name, [this.element]); | 66 TypeVariableType(this.name, [this.element]); |
| 36 | 67 |
| 37 toString() => name.slowToString(); | 68 Type subst(Link<Type> arguments, List<Type> parameters) { |
| 69 if (arguments.isEmpty()) { |
| 70 // Return fast on empty substitutions. |
| 71 return this; |
| 72 } |
| 73 Link<Type> argumentLink = arguments; |
| 74 Iterator<Type> parameterIterator = parameters.iterator(); |
| 75 while (!argumentLink.isEmpty() && parameterIterator.hasNext()) { |
| 76 Type parameter = parameterIterator.next(); |
| 77 Type argument = argumentLink.head; |
| 78 if (parameter === this) { |
| 79 return argument; |
| 80 } |
| 81 argumentLink = argumentLink.tail; |
| 82 } |
| 83 // The type variable was not substituted. |
| 84 return this; |
| 85 } |
| 86 |
| 87 String toString() => name.slowToString(); |
| 38 } | 88 } |
| 39 | 89 |
| 40 /** | 90 /** |
| 41 * A statement type tracks whether a statement returns or may return. | 91 * A statement type tracks whether a statement returns or may return. |
| 42 */ | 92 */ |
| 43 class StatementType implements Type { | 93 class StatementType implements Type { |
| 44 final String stringName; | 94 final String stringName; |
| 45 Element get element() => null; | 95 Element get element() => null; |
| 46 | 96 |
| 47 SourceString get name() => new SourceString(stringName); | 97 SourceString get name() => new SourceString(stringName); |
| 48 | 98 |
| 49 const StatementType(this.stringName); | 99 const StatementType(this.stringName); |
| 50 | 100 |
| 51 static final RETURNING = const StatementType('<returning>'); | 101 static final RETURNING = const StatementType('<returning>'); |
| 52 static final NOT_RETURNING = const StatementType('<not returning>'); | 102 static final NOT_RETURNING = const StatementType('<not returning>'); |
| 53 static final MAYBE_RETURNING = const StatementType('<maybe returning>'); | 103 static final MAYBE_RETURNING = const StatementType('<maybe returning>'); |
| 54 | 104 |
| 55 /** Combine the information about two control-flow edges that are joined. */ | 105 /** Combine the information about two control-flow edges that are joined. */ |
| 56 StatementType join(StatementType other) { | 106 StatementType join(StatementType other) { |
| 57 return (this === other) ? this : MAYBE_RETURNING; | 107 return (this === other) ? this : MAYBE_RETURNING; |
| 58 } | 108 } |
| 59 | 109 |
| 110 Type subst(Link<Type> arguments, List<Type> parameters) { |
| 111 // Statement types are not substitutable. |
| 112 return this; |
| 113 } |
| 114 |
| 60 String toString() => stringName; | 115 String toString() => stringName; |
| 61 } | 116 } |
| 62 | 117 |
| 63 class VoidType implements Type { | 118 class VoidType implements Type { |
| 64 const VoidType(this.element); | 119 const VoidType(this.element); |
| 65 SourceString get name() => element.name; | 120 SourceString get name() => element.name; |
| 66 final VoidElement element; | 121 final VoidElement element; |
| 67 | 122 |
| 68 toString() => name.slowToString(); | 123 Type subst(Link<Type> arguments, List<Type> parameters) { |
| 124 // Void cannot be substituted. |
| 125 return this; |
| 126 } |
| 127 |
| 128 String toString() => name.slowToString(); |
| 69 } | 129 } |
| 70 | 130 |
| 71 class InterfaceType implements Type { | 131 class InterfaceType implements Type { |
| 72 final Element element; | 132 final Element element; |
| 73 final Link<Type> arguments; | 133 final Link<Type> arguments; |
| 74 | 134 |
| 75 const InterfaceType(this.element, | 135 const InterfaceType(this.element, |
| 76 [this.arguments = const EmptyLink<Type>()]); | 136 [this.arguments = const EmptyLink<Type>()]); |
| 77 | 137 |
| 78 SourceString get name() => element.name; | 138 SourceString get name() => element.name; |
| 79 | 139 |
| 80 toString() { | 140 Type subst(Link<Type> replacements, List<Type> parameters) { |
| 141 if (arguments.isEmpty()) { |
| 142 // Return fast on non-generic types. |
| 143 return this; |
| 144 } |
| 145 if (replacements.isEmpty()) { |
| 146 // Return fast on empty substitutions. |
| 147 return this; |
| 148 } |
| 149 bool changed = false; |
| 150 var argumentsBuilder = new LinkBuilder<Type>(); |
| 151 Link<Type> argument = arguments; |
| 152 while (!argument.isEmpty()) { |
| 153 var replacement = argument.head.subst(replacements, parameters); |
| 154 if (!changed && replacement !== argument.head) { |
| 155 changed = true; |
| 156 } |
| 157 argumentsBuilder.addLast(replacement); |
| 158 argument = argument.tail; |
| 159 } |
| 160 if (changed) { |
| 161 // Create a new type only if necessary. |
| 162 return new InterfaceType(element, argumentsBuilder.toLink()); |
| 163 } |
| 164 return this; |
| 165 } |
| 166 |
| 167 String toString() { |
| 81 StringBuffer sb = new StringBuffer(); | 168 StringBuffer sb = new StringBuffer(); |
| 82 sb.add(name.slowToString()); | 169 sb.add(name.slowToString()); |
| 83 if (!arguments.isEmpty()) { | 170 if (!arguments.isEmpty()) { |
| 84 sb.add('<'); | 171 sb.add('<'); |
| 85 arguments.printOn(sb, ', '); | 172 arguments.printOn(sb, ', '); |
| 86 sb.add('>'); | 173 sb.add('>'); |
| 87 } | 174 } |
| 88 return sb.toString(); | 175 return sb.toString(); |
| 89 } | 176 } |
| 90 } | 177 } |
| 91 | 178 |
| 92 class FunctionType implements Type { | 179 class FunctionType implements Type { |
| 93 final Element element; | 180 final Element element; |
| 94 final Type returnType; | 181 final Type returnType; |
| 95 final Link<Type> parameterTypes; | 182 final Link<Type> parameterTypes; |
| 96 | 183 |
| 97 const FunctionType(Type this.returnType, Link<Type> this.parameterTypes, | 184 const FunctionType(Type this.returnType, Link<Type> this.parameterTypes, |
| 98 Element this.element); | 185 Element this.element); |
| 99 | 186 |
| 100 toString() { | 187 Type subst(Link<Type> arguments, List<Type> parameters) { |
| 188 if (arguments.isEmpty()) { |
| 189 // Return fast on empty substitutions. |
| 190 return this; |
| 191 } |
| 192 var newReturnType = returnType.subst(arguments, parameters); |
| 193 bool changed = newReturnType !== returnType; |
| 194 var parameterBuilder = new LinkBuilder<Type>(); |
| 195 Link<Type> parameterType = parameterTypes; |
| 196 while (!parameterType.isEmpty()) { |
| 197 var replacement = parameterType.head.subst(arguments, parameters); |
| 198 if (!changed && replacement !== parameterType.head) { |
| 199 changed = true; |
| 200 } |
| 201 parameterBuilder.addLast(replacement); |
| 202 parameterType = parameterType.tail; |
| 203 } |
| 204 if (changed) { |
| 205 // Create a new type only if necessary. |
| 206 return new FunctionType(newReturnType, parameterBuilder.toLink(), |
| 207 element); |
| 208 } |
| 209 return this; |
| 210 } |
| 211 |
| 212 String toString() { |
| 101 StringBuffer sb = new StringBuffer(); | 213 StringBuffer sb = new StringBuffer(); |
| 102 bool first = true; | 214 bool first = true; |
| 103 sb.add('('); | 215 sb.add('('); |
| 104 parameterTypes.printOn(sb, ', '); | 216 parameterTypes.printOn(sb, ', '); |
| 105 sb.add(') -> ${returnType}'); | 217 sb.add(') -> ${returnType}'); |
| 106 return sb.toString(); | 218 return sb.toString(); |
| 107 } | 219 } |
| 108 | 220 |
| 109 SourceString get name() => const SourceString('Function'); | 221 SourceString get name() => const SourceString('Function'); |
| 110 | 222 |
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 } | 884 } |
| 773 | 885 |
| 774 visitCatchBlock(CatchBlock node) { | 886 visitCatchBlock(CatchBlock node) { |
| 775 return unhandledStatement(); | 887 return unhandledStatement(); |
| 776 } | 888 } |
| 777 | 889 |
| 778 visitTypedef(Typedef node) { | 890 visitTypedef(Typedef node) { |
| 779 return unhandledStatement(); | 891 return unhandledStatement(); |
| 780 } | 892 } |
| 781 } | 893 } |
| OLD | NEW |