| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.type_checker; | 4 library kernel.type_checker; |
| 5 | 5 |
| 6 import 'ast.dart'; | 6 import 'ast.dart'; |
| 7 import 'class_hierarchy.dart'; | 7 import 'class_hierarchy.dart'; |
| 8 import 'core_types.dart'; | 8 import 'core_types.dart'; |
| 9 import 'type_algebra.dart'; | 9 import 'type_algebra.dart'; |
| 10 import 'type_environment.dart'; | 10 import 'type_environment.dart'; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 } | 151 } |
| 152 | 152 |
| 153 visitConstructor(Constructor node) { | 153 visitConstructor(Constructor node) { |
| 154 environment.returnType = null; | 154 environment.returnType = null; |
| 155 environment.yieldType = null; | 155 environment.yieldType = null; |
| 156 node.initializers.forEach(visitInitializer); | 156 node.initializers.forEach(visitInitializer); |
| 157 handleFunctionNode(node.function); | 157 handleFunctionNode(node.function); |
| 158 } | 158 } |
| 159 | 159 |
| 160 visitProcedure(Procedure node) { | 160 visitProcedure(Procedure node) { |
| 161 environment.returnType = node.function.returnType; | 161 environment.returnType = _getInternalReturnType(node.function); |
| 162 environment.yieldType = _getYieldType(node.function); | 162 environment.yieldType = _getYieldType(node.function); |
| 163 handleFunctionNode(node.function); | 163 handleFunctionNode(node.function); |
| 164 } | 164 } |
| 165 | 165 |
| 166 void handleFunctionNode(FunctionNode node) { | 166 void handleFunctionNode(FunctionNode node) { |
| 167 var oldAsyncMarker = environment.currentAsyncMarker; |
| 168 environment.currentAsyncMarker = node.asyncMarker; |
| 167 node.positionalParameters | 169 node.positionalParameters |
| 168 .skip(node.requiredParameterCount) | 170 .skip(node.requiredParameterCount) |
| 169 .forEach(handleOptionalParameter); | 171 .forEach(handleOptionalParameter); |
| 170 node.namedParameters.forEach(handleOptionalParameter); | 172 node.namedParameters.forEach(handleOptionalParameter); |
| 171 if (node.body != null) { | 173 if (node.body != null) { |
| 172 visitStatement(node.body); | 174 visitStatement(node.body); |
| 173 } | 175 } |
| 176 environment.currentAsyncMarker = oldAsyncMarker; |
| 174 } | 177 } |
| 175 | 178 |
| 176 void handleNestedFunctionNode(FunctionNode node) { | 179 void handleNestedFunctionNode(FunctionNode node) { |
| 177 var oldReturn = environment.returnType; | 180 var oldReturn = environment.returnType; |
| 178 var oldYield = environment.yieldType; | 181 var oldYield = environment.yieldType; |
| 179 environment.returnType = node.returnType; | 182 environment.returnType = _getInternalReturnType(node); |
| 180 environment.yieldType = _getYieldType(node); | 183 environment.yieldType = _getYieldType(node); |
| 181 handleFunctionNode(node); | 184 handleFunctionNode(node); |
| 182 environment.returnType = oldReturn; | 185 environment.returnType = oldReturn; |
| 183 environment.yieldType = oldYield; | 186 environment.yieldType = oldYield; |
| 184 } | 187 } |
| 185 | 188 |
| 186 void handleOptionalParameter(VariableDeclaration parameter) { | 189 void handleOptionalParameter(VariableDeclaration parameter) { |
| 187 if (parameter.initializer != null) { | 190 if (parameter.initializer != null) { |
| 188 checkAssignableExpression(parameter.initializer, parameter.type); | 191 checkAssignableExpression(parameter.initializer, parameter.type); |
| 189 } | 192 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 } | 271 } |
| 269 } | 272 } |
| 270 if (!found) { | 273 if (!found) { |
| 271 fail(argument.value, 'Unexpected named parameter: ${argument.name}'); | 274 fail(argument.value, 'Unexpected named parameter: ${argument.name}'); |
| 272 return const BottomType(); | 275 return const BottomType(); |
| 273 } | 276 } |
| 274 } | 277 } |
| 275 return substitution.substituteType(function.returnType); | 278 return substitution.substituteType(function.returnType); |
| 276 } | 279 } |
| 277 | 280 |
| 281 DartType _getInternalReturnType(FunctionNode function) { |
| 282 switch (function.asyncMarker) { |
| 283 case AsyncMarker.Sync: |
| 284 return function.returnType; |
| 285 |
| 286 case AsyncMarker.Async: |
| 287 Class container = coreTypes.futureClass; |
| 288 DartType returnType = function.returnType; |
| 289 if (returnType is InterfaceType && returnType.classNode == container) { |
| 290 return returnType.typeArguments.single; |
| 291 } |
| 292 return const DynamicType(); |
| 293 |
| 294 case AsyncMarker.SyncStar: |
| 295 case AsyncMarker.AsyncStar: |
| 296 case AsyncMarker.SyncYielding: |
| 297 return null; |
| 298 |
| 299 default: |
| 300 throw 'Unexpected async marker: ${function.asyncMarker}'; |
| 301 } |
| 302 } |
| 303 |
| 278 DartType _getYieldType(FunctionNode function) { | 304 DartType _getYieldType(FunctionNode function) { |
| 279 switch (function.asyncMarker) { | 305 switch (function.asyncMarker) { |
| 280 case AsyncMarker.Sync: | 306 case AsyncMarker.Sync: |
| 281 case AsyncMarker.Async: | 307 case AsyncMarker.Async: |
| 282 return null; | 308 return null; |
| 283 | 309 |
| 284 case AsyncMarker.SyncStar: | 310 case AsyncMarker.SyncStar: |
| 285 case AsyncMarker.AsyncStar: | 311 case AsyncMarker.AsyncStar: |
| 286 Class container = function.asyncMarker == AsyncMarker.SyncStar | 312 Class container = function.asyncMarker == AsyncMarker.SyncStar |
| 287 ? coreTypes.iterableClass | 313 ? coreTypes.iterableClass |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 visitLabeledStatement(LabeledStatement node) { | 755 visitLabeledStatement(LabeledStatement node) { |
| 730 visitStatement(node.body); | 756 visitStatement(node.body); |
| 731 } | 757 } |
| 732 | 758 |
| 733 @override | 759 @override |
| 734 visitReturnStatement(ReturnStatement node) { | 760 visitReturnStatement(ReturnStatement node) { |
| 735 if (node.expression != null) { | 761 if (node.expression != null) { |
| 736 if (environment.returnType == null) { | 762 if (environment.returnType == null) { |
| 737 fail(node, 'Return of a value from void method'); | 763 fail(node, 'Return of a value from void method'); |
| 738 } else { | 764 } else { |
| 739 checkAssignableExpression(node.expression, environment.returnType); | 765 var type = visitExpression(node.expression); |
| 766 if (environment.currentAsyncMarker == AsyncMarker.Async) { |
| 767 type = environment.unfutureType(type); |
| 768 } |
| 769 checkAssignable(node.expression, type, environment.returnType); |
| 740 } | 770 } |
| 741 } | 771 } |
| 742 } | 772 } |
| 743 | 773 |
| 744 @override | 774 @override |
| 745 visitSwitchStatement(SwitchStatement node) { | 775 visitSwitchStatement(SwitchStatement node) { |
| 746 visitExpression(node.expression); | 776 visitExpression(node.expression); |
| 747 for (var switchCase in node.cases) { | 777 for (var switchCase in node.cases) { |
| 748 switchCase.expressions.forEach(visitExpression); | 778 switchCase.expressions.forEach(visitExpression); |
| 749 visitStatement(switchCase.body); | 779 visitStatement(switchCase.body); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 772 } | 802 } |
| 773 | 803 |
| 774 @override | 804 @override |
| 775 visitWhileStatement(WhileStatement node) { | 805 visitWhileStatement(WhileStatement node) { |
| 776 checkAssignableExpression(node.condition, environment.boolType); | 806 checkAssignableExpression(node.condition, environment.boolType); |
| 777 visitStatement(node.body); | 807 visitStatement(node.body); |
| 778 } | 808 } |
| 779 | 809 |
| 780 @override | 810 @override |
| 781 visitYieldStatement(YieldStatement node) { | 811 visitYieldStatement(YieldStatement node) { |
| 782 checkAssignableExpression(node.expression, environment.yieldType); | 812 if (node.isYieldStar) { |
| 813 Class container = environment.currentAsyncMarker == AsyncMarker.AsyncStar |
| 814 ? coreTypes.streamClass |
| 815 : coreTypes.iterableClass; |
| 816 var type = visitExpression(node.expression); |
| 817 var asContainer = type is InterfaceType |
| 818 ? hierarchy.getTypeAsInstanceOf(type, container) |
| 819 : null; |
| 820 if (asContainer != null) { |
| 821 checkAssignable(node.expression, asContainer.typeArguments[0], |
| 822 environment.yieldType); |
| 823 } else { |
| 824 fail(node.expression, '$type is not an instance of $container'); |
| 825 } |
| 826 } else { |
| 827 checkAssignableExpression(node.expression, environment.yieldType); |
| 828 } |
| 783 } | 829 } |
| 784 | 830 |
| 785 @override | 831 @override |
| 786 visitFieldInitializer(FieldInitializer node) { | 832 visitFieldInitializer(FieldInitializer node) { |
| 787 checkAssignableExpression(node.value, node.field.type); | 833 checkAssignableExpression(node.value, node.field.type); |
| 788 } | 834 } |
| 789 | 835 |
| 790 @override | 836 @override |
| 791 visitRedirectingInitializer(RedirectingInitializer node) { | 837 visitRedirectingInitializer(RedirectingInitializer node) { |
| 792 handleCall(node.arguments, node.target.function, | 838 handleCall(node.arguments, node.target.function, |
| 793 typeParameters: const <TypeParameter>[]); | 839 typeParameters: const <TypeParameter>[]); |
| 794 } | 840 } |
| 795 | 841 |
| 796 @override | 842 @override |
| 797 visitSuperInitializer(SuperInitializer node) { | 843 visitSuperInitializer(SuperInitializer node) { |
| 798 handleCall(node.arguments, node.target.function, | 844 handleCall(node.arguments, node.target.function, |
| 799 typeParameters: const <TypeParameter>[]); | 845 typeParameters: const <TypeParameter>[]); |
| 800 } | 846 } |
| 801 | 847 |
| 802 @override | 848 @override |
| 803 visitLocalInitializer(LocalInitializer node) { | 849 visitLocalInitializer(LocalInitializer node) { |
| 804 visitVariableDeclaration(node.variable); | 850 visitVariableDeclaration(node.variable); |
| 805 } | 851 } |
| 806 | 852 |
| 807 @override | 853 @override |
| 808 visitInvalidInitializer(InvalidInitializer node) {} | 854 visitInvalidInitializer(InvalidInitializer node) {} |
| 809 } | 855 } |
| OLD | NEW |