Chromium Code Reviews| 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 | 4 |
| 5 library fasta.body_builder; | 5 library fasta.body_builder; |
| 6 | 6 |
| 7 import '../fasta_codes.dart' | 7 import '../fasta_codes.dart' |
| 8 show FastaMessage, codeExpectedButGot, codeExpectedFunctionBody; | 8 show FastaMessage, codeExpectedButGot, codeExpectedFunctionBody; |
| 9 | 9 |
| 10 import '../parser/parser.dart' show FormalParameterType, MemberKind, optional; | 10 import '../parser/parser.dart' show FormalParameterType, MemberKind, optional; |
| 11 | 11 |
| 12 import '../parser/identifier_context.dart' show IdentifierContext; | 12 import '../parser/identifier_context.dart' show IdentifierContext; |
| 13 | 13 |
| 14 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; | 14 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; |
| 15 | 15 |
| 16 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; | 16 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; |
| 17 | 17 |
| 18 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart' | 18 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart' |
| 19 show FieldNode; | 19 show FieldNode; |
| 20 | 20 |
| 21 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart' | 21 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart' |
| 22 show TypeInferrer; | 22 show TypeInferrer; |
| 23 | 23 |
| 24 import 'package:front_end/src/fasta/type_inference/type_promotion.dart' | 24 import 'package:front_end/src/fasta/type_inference/type_promotion.dart' |
| 25 show TypePromoter; | 25 show TypePromoter; |
| 26 | 26 |
| 27 import 'package:kernel/ast.dart'; | 27 import 'package:kernel/ast.dart' |
| 28 hide InvalidExpression, InvalidInitializer, InvalidStatement; | |
| 28 | 29 |
| 29 import 'package:kernel/clone.dart' show CloneVisitor; | 30 import 'package:kernel/clone.dart' show CloneVisitor; |
| 30 | 31 |
| 31 import 'package:kernel/transformations/flags.dart' show TransformerFlag; | 32 import 'package:kernel/transformations/flags.dart' show TransformerFlag; |
| 32 | 33 |
| 33 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; | 34 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; |
| 34 | 35 |
| 35 import 'package:kernel/core_types.dart' show CoreTypes; | 36 import 'package:kernel/core_types.dart' show CoreTypes; |
| 36 | 37 |
| 37 import 'frontend_accessors.dart' show buildIsNull, makeBinary, makeLet; | 38 import 'frontend_accessors.dart' show buildIsNull, makeBinary, makeLet; |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 var node = pop(); | 457 var node = pop(); |
| 457 Initializer initializer; | 458 Initializer initializer; |
| 458 if (node is Initializer) { | 459 if (node is Initializer) { |
| 459 initializer = node; | 460 initializer = node; |
| 460 } else if (node is FastaAccessor) { | 461 } else if (node is FastaAccessor) { |
| 461 initializer = node.buildFieldInitializer(fieldInitializers); | 462 initializer = node.buildFieldInitializer(fieldInitializers); |
| 462 } else if (node is ConstructorInvocation) { | 463 } else if (node is ConstructorInvocation) { |
| 463 initializer = | 464 initializer = |
| 464 buildSuperInitializer(node.target, node.arguments, token.charOffset); | 465 buildSuperInitializer(node.target, node.arguments, token.charOffset); |
| 465 } else { | 466 } else { |
| 467 Expression value = toValue(node); | |
| 466 if (node is! Throw) { | 468 if (node is! Throw) { |
| 467 // TODO(ahe): This is probably an internal error. | 469 value = wrapInCompileTimeError(value, "Expected an initializer."); |
| 468 needsImplicitSuperInitializer = false; | |
| 469 node = wrapInvalid(node); | |
| 470 } | 470 } |
| 471 initializer = buildInvalidIntializer(node, token.charOffset); | 471 initializer = buildInvalidIntializer(node, token.charOffset); |
| 472 } | 472 } |
| 473 _typeInferrer.inferInitializer(initializer); | 473 _typeInferrer.inferInitializer(initializer); |
| 474 if (member is KernelConstructorBuilder) { | 474 if (member is KernelConstructorBuilder) { |
| 475 member.addInitializer(initializer); | 475 member.addInitializer(initializer); |
| 476 } else { | 476 } else { |
| 477 addCompileTimeError( | 477 addCompileTimeError( |
| 478 token.charOffset, "Can't have initializers: ${member.name}"); | 478 token.charOffset, "Can't have initializers: ${member.name}"); |
| 479 } | 479 } |
| (...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1226 Block block = popBlock(count, beginToken); | 1226 Block block = popBlock(count, beginToken); |
| 1227 exitLocalScope(); | 1227 exitLocalScope(); |
| 1228 push(block); | 1228 push(block); |
| 1229 } | 1229 } |
| 1230 | 1230 |
| 1231 @override | 1231 @override |
| 1232 void handleAssignmentExpression(Token token) { | 1232 void handleAssignmentExpression(Token token) { |
| 1233 debugEvent("AssignmentExpression"); | 1233 debugEvent("AssignmentExpression"); |
| 1234 Expression value = popForValue(); | 1234 Expression value = popForValue(); |
| 1235 var accessor = pop(); | 1235 var accessor = pop(); |
| 1236 if (accessor is TypeDeclarationBuilder) { | 1236 if (accessor is TypeDeclarationBuilder || accessor is! FastaAccessor) { |
|
ahe
2017/05/29 13:14:47
This change is what's causing the new compile-time
| |
| 1237 push(wrapInvalid(new KernelTypeLiteral( | |
| 1238 accessor.buildTypesWithBuiltArguments(library, null)))); | |
| 1239 } else if (accessor is! FastaAccessor) { | |
| 1240 push(buildCompileTimeError("Can't assign to this.", token.charOffset)); | 1237 push(buildCompileTimeError("Can't assign to this.", token.charOffset)); |
| 1241 } else { | 1238 } else { |
| 1242 push(new DelayedAssignment( | 1239 push(new DelayedAssignment( |
| 1243 this, token, accessor, value, token.stringValue)); | 1240 this, token, accessor, value, token.stringValue)); |
| 1244 } | 1241 } |
| 1245 } | 1242 } |
| 1246 | 1243 |
| 1247 @override | 1244 @override |
| 1248 void enterLoop(int charOffset) { | 1245 void enterLoop(int charOffset) { |
| 1249 if (peek() is LabelTarget) { | 1246 if (peek() is LabelTarget) { |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1760 VariableDeclaration stackTrace; | 1757 VariableDeclaration stackTrace; |
| 1761 if (catchParameters != null) { | 1758 if (catchParameters != null) { |
| 1762 if (catchParameters.required.length > 0) { | 1759 if (catchParameters.required.length > 0) { |
| 1763 exception = catchParameters.required[0]; | 1760 exception = catchParameters.required[0]; |
| 1764 } | 1761 } |
| 1765 if (catchParameters.required.length > 1) { | 1762 if (catchParameters.required.length > 1) { |
| 1766 stackTrace = catchParameters.required[1]; | 1763 stackTrace = catchParameters.required[1]; |
| 1767 } | 1764 } |
| 1768 if (catchParameters.required.length > 2 || | 1765 if (catchParameters.required.length > 2 || |
| 1769 catchParameters.optional != null) { | 1766 catchParameters.optional != null) { |
| 1770 body = new Block(<Statement>[new InvalidStatement()]); | 1767 body = new Block(<Statement>[ |
| 1771 compileTimeErrorInTry ??= buildCompileTimeErrorStatement( | 1768 compileTimeErrorInTry ??= buildCompileTimeErrorStatement( |
| 1772 "Invalid catch arguments.", catchKeyword.next.charOffset); | 1769 "Invalid catch arguments.", catchKeyword.next.charOffset) |
| 1770 ]); | |
| 1773 } | 1771 } |
| 1774 } | 1772 } |
| 1775 push(new Catch(exception, body, guard: type, stackTrace: stackTrace)); | 1773 push(new Catch(exception, body, guard: type, stackTrace: stackTrace)); |
| 1776 } | 1774 } |
| 1777 | 1775 |
| 1778 @override | 1776 @override |
| 1779 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { | 1777 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { |
| 1780 Statement finallyBlock = popStatementIfNotNull(finallyKeyword); | 1778 Statement finallyBlock = popStatementIfNotNull(finallyKeyword); |
| 1781 List<Catch> catches = popList(catchCount); | 1779 List<Catch> catches = popList(catchCount); |
| 1782 Statement tryBlock = popStatement(); | 1780 Statement tryBlock = popStatement(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1848 } | 1846 } |
| 1849 | 1847 |
| 1850 @override | 1848 @override |
| 1851 void handleUnaryPrefixAssignmentExpression(Token token) { | 1849 void handleUnaryPrefixAssignmentExpression(Token token) { |
| 1852 debugEvent("UnaryPrefixAssignmentExpression"); | 1850 debugEvent("UnaryPrefixAssignmentExpression"); |
| 1853 var accessor = pop(); | 1851 var accessor = pop(); |
| 1854 if (accessor is FastaAccessor) { | 1852 if (accessor is FastaAccessor) { |
| 1855 push(accessor.buildPrefixIncrement(incrementOperator(token), | 1853 push(accessor.buildPrefixIncrement(incrementOperator(token), |
| 1856 offset: token.charOffset)); | 1854 offset: token.charOffset)); |
| 1857 } else { | 1855 } else { |
| 1858 push(wrapInvalid(toValue(accessor))); | 1856 push(wrapInCompileTimeError(toValue(accessor), "Can't assign to this.")); |
| 1859 } | 1857 } |
| 1860 } | 1858 } |
| 1861 | 1859 |
| 1862 @override | 1860 @override |
| 1863 void handleUnaryPostfixAssignmentExpression(Token token) { | 1861 void handleUnaryPostfixAssignmentExpression(Token token) { |
| 1864 debugEvent("UnaryPostfixAssignmentExpression"); | 1862 debugEvent("UnaryPostfixAssignmentExpression"); |
| 1865 var accessor = pop(); | 1863 var accessor = pop(); |
| 1866 if (accessor is FastaAccessor) { | 1864 if (accessor is FastaAccessor) { |
| 1867 push(new DelayedPostfixIncrement( | 1865 push(new DelayedPostfixIncrement( |
| 1868 this, token, accessor, incrementOperator(token), null)); | 1866 this, token, accessor, incrementOperator(token), null)); |
| 1869 } else { | 1867 } else { |
| 1870 push(wrapInvalid(toValue(accessor))); | 1868 push(wrapInCompileTimeError(toValue(accessor), "Can't assign to this.")); |
| 1871 } | 1869 } |
| 1872 } | 1870 } |
| 1873 | 1871 |
| 1874 @override | 1872 @override |
| 1875 void endConstructorReference( | 1873 void endConstructorReference( |
| 1876 Token start, Token periodBeforeName, Token endToken) { | 1874 Token start, Token periodBeforeName, Token endToken) { |
| 1877 debugEvent("ConstructorReference"); | 1875 debugEvent("ConstructorReference"); |
| 1878 // A constructor reference can contain up to three identifiers: | 1876 // A constructor reference can contain up to three identifiers: |
| 1879 // | 1877 // |
| 1880 // a) type <type-arguments>? | 1878 // a) type <type-arguments>? |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2130 | 2128 |
| 2131 @override | 2129 @override |
| 2132 void endFunctionName(Token beginToken, Token token) { | 2130 void endFunctionName(Token beginToken, Token token) { |
| 2133 debugEvent("FunctionName"); | 2131 debugEvent("FunctionName"); |
| 2134 Identifier name = pop(); | 2132 Identifier name = pop(); |
| 2135 VariableDeclaration variable = new KernelVariableDeclaration( | 2133 VariableDeclaration variable = new KernelVariableDeclaration( |
| 2136 name.name, functionNestingLevel, | 2134 name.name, functionNestingLevel, |
| 2137 isFinal: true, isLocalFunction: true) | 2135 isFinal: true, isLocalFunction: true) |
| 2138 ..fileOffset = offsetForToken(name.token); | 2136 ..fileOffset = offsetForToken(name.token); |
| 2139 push(new KernelFunctionDeclaration( | 2137 push(new KernelFunctionDeclaration( |
| 2140 variable, new FunctionNode(new InvalidStatement())) | 2138 variable, |
| 2139 // The function node is created later. | |
| 2140 null) | |
| 2141 ..fileOffset = beginToken.charOffset); | 2141 ..fileOffset = beginToken.charOffset); |
| 2142 declareVariable(variable); | 2142 declareVariable(variable); |
| 2143 enterLocalScope(); | 2143 enterLocalScope(); |
| 2144 } | 2144 } |
| 2145 | 2145 |
| 2146 void enterFunction() { | 2146 void enterFunction() { |
| 2147 debugEvent("enterFunction"); | 2147 debugEvent("enterFunction"); |
| 2148 functionNestingLevel++; | 2148 functionNestingLevel++; |
| 2149 push(switchScope ?? NullValue.SwitchScope); | 2149 push(switchScope ?? NullValue.SwitchScope); |
| 2150 switchScope = null; | 2150 switchScope = null; |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2651 @override | 2651 @override |
| 2652 Expression buildCompileTimeError(error, [int charOffset = -1]) { | 2652 Expression buildCompileTimeError(error, [int charOffset = -1]) { |
| 2653 // TODO(ahe): This method should be passed the erroneous expression, wrap | 2653 // TODO(ahe): This method should be passed the erroneous expression, wrap |
| 2654 // it in a class (TBD) from which the erroneous expression can be easily | 2654 // it in a class (TBD) from which the erroneous expression can be easily |
| 2655 // extracted. Similar for statements and initializers. See also [issue | 2655 // extracted. Similar for statements and initializers. See also [issue |
| 2656 // 29717](https://github.com/dart-lang/sdk/issues/29717) | 2656 // 29717](https://github.com/dart-lang/sdk/issues/29717) |
| 2657 addCompileTimeError(charOffset, error); | 2657 addCompileTimeError(charOffset, error); |
| 2658 String message = formatUnexpected(uri, charOffset, error); | 2658 String message = formatUnexpected(uri, charOffset, error); |
| 2659 Builder constructor = library.loader.getCompileTimeError(); | 2659 Builder constructor = library.loader.getCompileTimeError(); |
| 2660 return new Throw(buildStaticInvocation(constructor.target, | 2660 return new Throw(buildStaticInvocation(constructor.target, |
| 2661 new KernelArguments(<Expression>[new StringLiteral(message)]))); | 2661 new KernelArguments(<Expression>[new StringLiteral(message)]), |
| 2662 charOffset: charOffset)); | |
| 2663 } | |
| 2664 | |
| 2665 Expression wrapInCompileTimeError(Expression expression, String message) { | |
| 2666 return new Let( | |
| 2667 new VariableDeclaration.forValue(expression) | |
| 2668 ..fileOffset = expression.fileOffset, | |
| 2669 buildCompileTimeError(message, expression.fileOffset)) | |
| 2670 ..fileOffset = expression.fileOffset; | |
| 2662 } | 2671 } |
| 2663 | 2672 |
| 2664 Expression buildAbstractClassInstantiationError(String className, | 2673 Expression buildAbstractClassInstantiationError(String className, |
| 2665 [int charOffset = -1]) { | 2674 [int charOffset = -1]) { |
| 2666 warning("The class '$className' is abstract and can't be instantiated.", | 2675 warning("The class '$className' is abstract and can't be instantiated.", |
| 2667 charOffset); | 2676 charOffset); |
| 2668 Builder constructor = library.loader.getAbstractClassInstantiationError(); | 2677 Builder constructor = library.loader.getAbstractClassInstantiationError(); |
| 2669 return new Throw(buildStaticInvocation(constructor.target, | 2678 return new Throw(buildStaticInvocation(constructor.target, |
| 2670 new KernelArguments(<Expression>[new StringLiteral(className)]))); | 2679 new KernelArguments(<Expression>[new StringLiteral(className)]))); |
| 2671 } | 2680 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 2702 } | 2711 } |
| 2703 | 2712 |
| 2704 @override | 2713 @override |
| 2705 Expression buildProblemExpression(ProblemBuilder builder, int charOffset) { | 2714 Expression buildProblemExpression(ProblemBuilder builder, int charOffset) { |
| 2706 return buildCompileTimeError(builder.message, charOffset); | 2715 return buildCompileTimeError(builder.message, charOffset); |
| 2707 } | 2716 } |
| 2708 | 2717 |
| 2709 @override | 2718 @override |
| 2710 void handleOperator(Token token) { | 2719 void handleOperator(Token token) { |
| 2711 debugEvent("Operator"); | 2720 debugEvent("Operator"); |
| 2712 push(new Operator(token.stringValue)..fileOffset = token.charOffset); | 2721 push(new Operator(token.stringValue, token.charOffset)); |
| 2713 } | 2722 } |
| 2714 | 2723 |
| 2715 @override | 2724 @override |
| 2716 void handleSymbolVoid(Token token) { | 2725 void handleSymbolVoid(Token token) { |
| 2717 debugEvent("SymbolVoid"); | 2726 debugEvent("SymbolVoid"); |
| 2718 push(new Identifier(token)); | 2727 push(new Identifier(token)); |
| 2719 } | 2728 } |
| 2720 | 2729 |
| 2721 @override | 2730 @override |
| 2722 dynamic addCompileTimeError(int charOffset, String message, | 2731 dynamic addCompileTimeError(int charOffset, String message, |
| 2723 {bool silent: false}) { | 2732 {bool silent: false}) { |
| 2724 // TODO(ahe): If constantExpressionRequired is set, set it to false to | 2733 // TODO(ahe): If constantExpressionRequired is set, set it to false to |
| 2725 // avoid a long list of errors. | 2734 // avoid a long list of errors. |
| 2726 return library.addCompileTimeError(charOffset, message, fileUri: uri); | 2735 return library.addCompileTimeError(charOffset, message, fileUri: uri); |
| 2727 } | 2736 } |
| 2728 | 2737 |
| 2729 @override | 2738 @override |
| 2730 void handleInvalidFunctionBody(Token token) { | 2739 void handleInvalidFunctionBody(Token token) { |
| 2731 if (member.isNative) { | 2740 if (member.isNative) { |
| 2732 push(NullValue.FunctionBody); | 2741 push(NullValue.FunctionBody); |
| 2733 } else { | 2742 } else { |
| 2734 push(new Block(<Statement>[new InvalidStatement()])); | 2743 push(new Block(<Statement>[ |
| 2744 buildCompileTimeErrorStatement("Expected '{'.", token.charOffset) | |
| 2745 ])); | |
| 2735 } | 2746 } |
| 2736 } | 2747 } |
| 2737 | 2748 |
| 2738 @override | 2749 @override |
| 2739 void warning(String message, [int charOffset = -1]) { | 2750 void warning(String message, [int charOffset = -1]) { |
| 2740 if (constantExpressionRequired) { | 2751 if (constantExpressionRequired) { |
| 2741 addCompileTimeError(charOffset, message); | 2752 addCompileTimeError(charOffset, message); |
| 2742 } else { | 2753 } else { |
| 2743 super.warning(message, charOffset); | 2754 super.warning(message, charOffset); |
| 2744 } | 2755 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2793 final Token token; | 2804 final Token token; |
| 2794 String get name => token.lexeme; | 2805 String get name => token.lexeme; |
| 2795 | 2806 |
| 2796 Identifier(this.token); | 2807 Identifier(this.token); |
| 2797 | 2808 |
| 2798 Expression get initializer => null; | 2809 Expression get initializer => null; |
| 2799 | 2810 |
| 2800 String toString() => "identifier($name)"; | 2811 String toString() => "identifier($name)"; |
| 2801 } | 2812 } |
| 2802 | 2813 |
| 2803 // TODO(ahe): Shouldn't need to be an expression. | 2814 class Operator { |
| 2804 class Operator extends InvalidExpression { | |
| 2805 final String name; | 2815 final String name; |
| 2806 | 2816 |
| 2807 Operator(this.name); | 2817 final int charOffset; |
| 2818 | |
| 2819 Operator(this.name, this.charOffset); | |
| 2808 | 2820 |
| 2809 String toString() => "operator($name)"; | 2821 String toString() => "operator($name)"; |
| 2810 } | 2822 } |
| 2811 | 2823 |
| 2812 class InitializedIdentifier extends Identifier { | 2824 class InitializedIdentifier extends Identifier { |
| 2813 final Expression initializer; | 2825 final Expression initializer; |
| 2814 | 2826 |
| 2815 InitializedIdentifier(Token token, this.initializer) : super(token); | 2827 InitializedIdentifier(Token token, this.initializer) : super(token); |
| 2816 | 2828 |
| 2817 String toString() => "initialized-identifier($name, $initializer)"; | 2829 String toString() => "initialized-identifier($name, $initializer)"; |
| 2818 } | 2830 } |
| 2819 | 2831 |
| 2820 // TODO(ahe): Shouldn't need to be an expression. | 2832 class Label { |
| 2821 class Label extends InvalidExpression { | |
| 2822 String name; | 2833 String name; |
| 2823 | 2834 |
| 2824 Label(this.name); | 2835 Label(this.name); |
| 2825 | 2836 |
| 2826 String toString() => "label($name)"; | 2837 String toString() => "label($name)"; |
| 2827 } | 2838 } |
| 2828 | 2839 |
| 2829 abstract class ContextAccessor extends FastaAccessor { | 2840 abstract class ContextAccessor extends FastaAccessor { |
| 2830 final BuilderHelper helper; | 2841 final BuilderHelper helper; |
| 2831 | 2842 |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3238 if (starToken == null) { | 3249 if (starToken == null) { |
| 3239 return AsyncMarker.Async; | 3250 return AsyncMarker.Async; |
| 3240 } else { | 3251 } else { |
| 3241 assert(identical(starToken.stringValue, "*")); | 3252 assert(identical(starToken.stringValue, "*")); |
| 3242 return AsyncMarker.AsyncStar; | 3253 return AsyncMarker.AsyncStar; |
| 3243 } | 3254 } |
| 3244 } else { | 3255 } else { |
| 3245 return internalError("Unknown async modifier: $asyncToken"); | 3256 return internalError("Unknown async modifier: $asyncToken"); |
| 3246 } | 3257 } |
| 3247 } | 3258 } |
| OLD | NEW |