| 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 '../parser/parser.dart' show FormalParameterType, optional; | 7 import '../parser/parser.dart' show FormalParameterType, optional; |
| 8 | 8 |
| 9 import '../parser/error_kind.dart' show ErrorKind; | 9 import '../parser/error_kind.dart' show ErrorKind; |
| 10 | 10 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 node.name.name, new Arguments.empty(), node.fileOffset, | 181 node.name.name, new Arguments.empty(), node.fileOffset, |
| 182 isGetter: true); | 182 isGetter: true); |
| 183 } else if (node is BuilderAccessor) { | 183 } else if (node is BuilderAccessor) { |
| 184 return node.buildSimpleRead(); | 184 return node.buildSimpleRead(); |
| 185 } else if (node is TypeVariableBuilder) { | 185 } else if (node is TypeVariableBuilder) { |
| 186 TypeParameterType type = node.buildTypesWithBuiltArguments(library, null); | 186 TypeParameterType type = node.buildTypesWithBuiltArguments(library, null); |
| 187 if (!isInstanceContext && type.parameter.parent is Class) { | 187 if (!isInstanceContext && type.parameter.parent is Class) { |
| 188 return buildCompileTimeError( | 188 return buildCompileTimeError( |
| 189 "Type variables can only be used in instance methods."); | 189 "Type variables can only be used in instance methods."); |
| 190 } else { | 190 } else { |
| 191 if (constantExpressionRequired) { |
| 192 addCompileTimeError(-1, |
| 193 "Type variable can't be used as a constant expression $type."); |
| 194 } |
| 191 return new TypeLiteral(type); | 195 return new TypeLiteral(type); |
| 192 } | 196 } |
| 193 } else if (node is TypeDeclarationBuilder) { | 197 } else if (node is TypeDeclarationBuilder) { |
| 194 return new TypeLiteral(node.buildTypesWithBuiltArguments(library, null)); | 198 return new TypeLiteral(node.buildTypesWithBuiltArguments(library, null)); |
| 195 } else if (node is KernelTypeBuilder) { | 199 } else if (node is KernelTypeBuilder) { |
| 196 return new TypeLiteral(node.build(library)); | 200 return new TypeLiteral(node.build(library)); |
| 197 } else if (node is Expression) { | 201 } else if (node is Expression) { |
| 198 return node; | 202 return node; |
| 199 } else if (node is PrefixBuilder) { | 203 } else if (node is PrefixBuilder) { |
| 200 return buildCompileTimeError("A library can't be used as an expression."); | 204 return buildCompileTimeError("A library can't be used as an expression."); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 } else if (arguments == null) { | 537 } else if (arguments == null) { |
| 534 push(receiver); | 538 push(receiver); |
| 535 } else { | 539 } else { |
| 536 push(finishSend(receiver, arguments, beginToken.charOffset)); | 540 push(finishSend(receiver, arguments, beginToken.charOffset)); |
| 537 } | 541 } |
| 538 } | 542 } |
| 539 | 543 |
| 540 @override | 544 @override |
| 541 finishSend(Object receiver, Arguments arguments, int charOffset) { | 545 finishSend(Object receiver, Arguments arguments, int charOffset) { |
| 542 if (receiver is BuilderAccessor) { | 546 if (receiver is BuilderAccessor) { |
| 547 if (constantExpressionRequired) { |
| 548 addCompileTimeError(charOffset, "Not a constant expression."); |
| 549 } |
| 543 return receiver.doInvocation(charOffset, arguments); | 550 return receiver.doInvocation(charOffset, arguments); |
| 544 } else if (receiver is UnresolvedIdentifier) { | 551 } else if (receiver is UnresolvedIdentifier) { |
| 545 return throwNoSuchMethodError( | 552 return throwNoSuchMethodError( |
| 546 receiver.name.name, arguments, receiver.fileOffset); | 553 receiver.name.name, arguments, receiver.fileOffset); |
| 547 } else { | 554 } else { |
| 548 return buildMethodInvocation( | 555 return buildMethodInvocation( |
| 549 toValue(receiver), callName, arguments, charOffset); | 556 toValue(receiver), callName, arguments, charOffset); |
| 550 } | 557 } |
| 551 } | 558 } |
| 552 | 559 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 String name = token.lexeme; | 747 String name = token.lexeme; |
| 741 if (context.isScopeReference) { | 748 if (context.isScopeReference) { |
| 742 assert(!inInitializer || | 749 assert(!inInitializer || |
| 743 this.scope == enclosingScope || | 750 this.scope == enclosingScope || |
| 744 this.scope.parent == enclosingScope); | 751 this.scope.parent == enclosingScope); |
| 745 // This deals with this kind of initializer: `C(a) : a = a;` | 752 // This deals with this kind of initializer: `C(a) : a = a;` |
| 746 Scope scope = inInitializer ? enclosingScope : this.scope; | 753 Scope scope = inInitializer ? enclosingScope : this.scope; |
| 747 Builder builder = scope.lookup(name, token.charOffset, uri); | 754 Builder builder = scope.lookup(name, token.charOffset, uri); |
| 748 push(builderToFirstExpression(builder, name, token.charOffset)); | 755 push(builderToFirstExpression(builder, name, token.charOffset)); |
| 749 } else { | 756 } else { |
| 757 if (constantExpressionRequired) { |
| 758 if (context != IdentifierContext.namedArgumentReference && |
| 759 context != IdentifierContext.constructorReferenceContinuation && |
| 760 context != IdentifierContext.expressionContinuation && |
| 761 context != IdentifierContext.typeReferenceContinuation && |
| 762 context != IdentifierContext.localVariableDeclaration && |
| 763 context != |
| 764 IdentifierContext |
| 765 .constructorReferenceContinuationAfterTypeArguments) { |
| 766 addCompileTimeError( |
| 767 token.charOffset, "Not a constant expression: $context"); |
| 768 } |
| 769 } |
| 750 push(new Identifier(name)..fileOffset = token.charOffset); | 770 push(new Identifier(name)..fileOffset = token.charOffset); |
| 751 } | 771 } |
| 752 } | 772 } |
| 753 | 773 |
| 754 @override | 774 @override |
| 755 builderToFirstExpression(Builder builder, String name, int charOffset, | 775 builderToFirstExpression(Builder builder, String name, int charOffset, |
| 756 {bool isPrefix: false}) { | 776 {bool isPrefix: false}) { |
| 757 if (builder == null || (!isInstanceContext && builder.isInstanceMember)) { | 777 if (builder == null || (!isInstanceContext && builder.isInstanceMember)) { |
| 758 Name n = new Name(name, library.library); | 778 Name n = new Name(name, library.library); |
| 759 if (!isPrefix && isInstanceContext) { | 779 if (!isPrefix && isInstanceContext) { |
| 760 assert(builder == null); | 780 assert(builder == null); |
| 781 if (constantExpressionRequired) { |
| 782 addCompileTimeError(charOffset, "Not a constant expression."); |
| 783 } |
| 761 return new ThisPropertyAccessor(this, charOffset, n, null, null); | 784 return new ThisPropertyAccessor(this, charOffset, n, null, null); |
| 762 } else { | 785 } else { |
| 786 if (constantExpressionRequired) { |
| 787 addCompileTimeError(charOffset, "Not a constant expression."); |
| 788 } |
| 763 return new UnresolvedIdentifier(n)..fileOffset = charOffset; | 789 return new UnresolvedIdentifier(n)..fileOffset = charOffset; |
| 764 } | 790 } |
| 765 } else if (builder.isTypeDeclaration) { | 791 } else if (builder.isTypeDeclaration) { |
| 792 if (constantExpressionRequired && builder.isTypeVariable) { |
| 793 addCompileTimeError(charOffset, "Not a constant expression."); |
| 794 } |
| 766 return builder; | 795 return builder; |
| 767 } else if (builder.isLocal) { | 796 } else if (builder.isLocal) { |
| 797 if (constantExpressionRequired && !builder.isConst) { |
| 798 addCompileTimeError(charOffset, "Not a constant expression."); |
| 799 } |
| 768 return new VariableAccessor(this, charOffset, builder.target); | 800 return new VariableAccessor(this, charOffset, builder.target); |
| 769 } else if (builder.isInstanceMember) { | 801 } else if (builder.isInstanceMember) { |
| 802 if (constantExpressionRequired) { |
| 803 addCompileTimeError(charOffset, "Not a constant expression."); |
| 804 } |
| 770 return new ThisPropertyAccessor( | 805 return new ThisPropertyAccessor( |
| 771 this, charOffset, new Name(name, library.library), null, null); | 806 this, charOffset, new Name(name, library.library), null, null); |
| 772 } else if (builder.isRegularMethod) { | 807 } else if (builder.isRegularMethod) { |
| 773 assert(builder.isStatic || builder.isTopLevel); | 808 assert(builder.isStatic || builder.isTopLevel); |
| 774 return new StaticAccessor(this, charOffset, builder.target, null); | 809 return new StaticAccessor(this, charOffset, builder.target, null); |
| 775 } else if (builder is PrefixBuilder) { | 810 } else if (builder is PrefixBuilder) { |
| 776 return builder; | 811 return builder; |
| 777 } else if (builder is MixedAccessor) { | 812 } else if (builder is MixedAccessor) { |
| 813 if (constantExpressionRequired && !builder.getter.target.isConst) { |
| 814 addCompileTimeError(charOffset, "Not a constant expression."); |
| 815 } |
| 778 return new StaticAccessor( | 816 return new StaticAccessor( |
| 779 this, charOffset, builder.getter.target, builder.setter.target); | 817 this, charOffset, builder.getter.target, builder.setter.target); |
| 780 } else { | 818 } else { |
| 781 if (builder.hasProblem && builder is! AccessErrorBuilder) return builder; | 819 if (builder.hasProblem && builder is! AccessErrorBuilder) return builder; |
| 782 Builder setter; | 820 Builder setter; |
| 783 if (builder.isSetter) { | 821 if (builder.isSetter) { |
| 784 setter = builder; | 822 setter = builder; |
| 785 } else if (builder.isGetter) { | 823 } else if (builder.isGetter) { |
| 786 setter = scope.lookupSetter(name, charOffset, uri); | 824 setter = scope.lookupSetter(name, charOffset, uri); |
| 787 } else if (builder.isField && !builder.isFinal) { | 825 } else if (builder.isField && !builder.isFinal) { |
| 788 setter = builder; | 826 setter = builder; |
| 789 } | 827 } |
| 790 return new StaticAccessor.fromBuilder(this, builder, charOffset, setter); | 828 StaticAccessor accessor = |
| 829 new StaticAccessor.fromBuilder(this, builder, charOffset, setter); |
| 830 if (constantExpressionRequired) { |
| 831 Member readTarget = accessor.readTarget; |
| 832 if (!(readTarget is Field && readTarget.isConst)) { |
| 833 addCompileTimeError(charOffset, "Not a constant expression."); |
| 834 } |
| 835 } |
| 836 return accessor; |
| 791 } | 837 } |
| 792 } | 838 } |
| 793 | 839 |
| 794 @override | 840 @override |
| 795 void handleQualified(Token period) { | 841 void handleQualified(Token period) { |
| 796 debugEvent("Qualified"); | 842 debugEvent("Qualified"); |
| 797 Identifier name = pop(); | 843 Identifier name = pop(); |
| 798 var receiver = pop(); | 844 var receiver = pop(); |
| 799 push([receiver, name]); | 845 push([receiver, name]); |
| 800 } | 846 } |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1208 if (builder == null) { | 1254 if (builder == null) { |
| 1209 warning("Type not found: '$name'.", charOffset); | 1255 warning("Type not found: '$name'.", charOffset); |
| 1210 return const DynamicType(); | 1256 return const DynamicType(); |
| 1211 } else { | 1257 } else { |
| 1212 return kernelTypeFromBuilder(builder, arguments, charOffset); | 1258 return kernelTypeFromBuilder(builder, arguments, charOffset); |
| 1213 } | 1259 } |
| 1214 } | 1260 } |
| 1215 | 1261 |
| 1216 DartType kernelTypeFromBuilder( | 1262 DartType kernelTypeFromBuilder( |
| 1217 Builder builder, List<DartType> arguments, int charOffset) { | 1263 Builder builder, List<DartType> arguments, int charOffset) { |
| 1264 if (constantExpressionRequired && builder is TypeVariableBuilder) { |
| 1265 addCompileTimeError(charOffset, "Not a constant expression."); |
| 1266 } |
| 1218 if (builder is TypeDeclarationBuilder) { | 1267 if (builder is TypeDeclarationBuilder) { |
| 1219 return builder.buildTypesWithBuiltArguments(library, arguments); | 1268 return builder.buildTypesWithBuiltArguments(library, arguments); |
| 1220 } else if (builder.hasProblem) { | 1269 } else if (builder.hasProblem) { |
| 1221 ProblemBuilder problem = builder; | 1270 ProblemBuilder problem = builder; |
| 1222 addCompileTimeError(charOffset, problem.message); | 1271 addCompileTimeError(charOffset, problem.message); |
| 1223 } else { | 1272 } else { |
| 1224 warning("Not a type: '${builder.fullNameForErrors}'.", charOffset); | 1273 warning("Not a type: '${builder.fullNameForErrors}'.", charOffset); |
| 1225 } | 1274 } |
| 1226 // TODO(ahe): Create an error somehow. | 1275 // TODO(ahe): Create an error somehow. |
| 1227 return const DynamicType(); | 1276 return const DynamicType(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 if (name is Identifier) { | 1314 if (name is Identifier) { |
| 1266 name = name.name; | 1315 name = name.name; |
| 1267 } | 1316 } |
| 1268 if (name is BuilderAccessor) { | 1317 if (name is BuilderAccessor) { |
| 1269 warning("'${beginToken.lexeme}' isn't a type.", beginToken.charOffset); | 1318 warning("'${beginToken.lexeme}' isn't a type.", beginToken.charOffset); |
| 1270 push(const DynamicType()); | 1319 push(const DynamicType()); |
| 1271 } else if (name is UnresolvedIdentifier) { | 1320 } else if (name is UnresolvedIdentifier) { |
| 1272 warning("'${name.name}' isn't a type.", beginToken.charOffset); | 1321 warning("'${name.name}' isn't a type.", beginToken.charOffset); |
| 1273 push(const DynamicType()); | 1322 push(const DynamicType()); |
| 1274 } else if (name is TypeVariableBuilder) { | 1323 } else if (name is TypeVariableBuilder) { |
| 1324 if (constantExpressionRequired) { |
| 1325 addCompileTimeError( |
| 1326 beginToken.charOffset, "Not a constant expression."); |
| 1327 } |
| 1275 push(name.buildTypesWithBuiltArguments(library, arguments)); | 1328 push(name.buildTypesWithBuiltArguments(library, arguments)); |
| 1276 } else if (name is TypeDeclarationBuilder) { | 1329 } else if (name is TypeDeclarationBuilder) { |
| 1277 push(name.buildTypesWithBuiltArguments(library, arguments)); | 1330 push(name.buildTypesWithBuiltArguments(library, arguments)); |
| 1278 } else if (name is TypeBuilder) { | 1331 } else if (name is TypeBuilder) { |
| 1279 push(name.build(library)); | 1332 push(name.build(library)); |
| 1280 } else if (name is Builder) { | 1333 } else if (name is Builder) { |
| 1281 push(kernelTypeFromBuilder(name, arguments, beginToken.charOffset)); | 1334 push(kernelTypeFromBuilder(name, arguments, beginToken.charOffset)); |
| 1282 } else if (name is String) { | 1335 } else if (name is String) { |
| 1283 push(kernelTypeFromString(name, arguments, beginToken.charOffset)); | 1336 push(kernelTypeFromString(name, arguments, beginToken.charOffset)); |
| 1284 } else { | 1337 } else { |
| (...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2341 push(new Operator(token.stringValue)..fileOffset = token.charOffset); | 2394 push(new Operator(token.stringValue)..fileOffset = token.charOffset); |
| 2342 } | 2395 } |
| 2343 | 2396 |
| 2344 @override | 2397 @override |
| 2345 void handleSymbolVoid(Token token) { | 2398 void handleSymbolVoid(Token token) { |
| 2346 logEvent("SymbolVoid"); | 2399 logEvent("SymbolVoid"); |
| 2347 } | 2400 } |
| 2348 | 2401 |
| 2349 dynamic addCompileTimeError(int charOffset, String message, | 2402 dynamic addCompileTimeError(int charOffset, String message, |
| 2350 {bool silent: false}) { | 2403 {bool silent: false}) { |
| 2404 // TODO(ahe): If constantExpressionRequired is set, set it to false to |
| 2405 // avoid a long list of errors. |
| 2351 return library.addCompileTimeError(charOffset, message, fileUri: uri); | 2406 return library.addCompileTimeError(charOffset, message, fileUri: uri); |
| 2352 } | 2407 } |
| 2353 | 2408 |
| 2354 @override | 2409 @override |
| 2355 void handleInvalidFunctionBody(Token token) { | 2410 void handleInvalidFunctionBody(Token token) { |
| 2356 if (member.isNative) { | 2411 if (member.isNative) { |
| 2357 push(NullValue.FunctionBody); | 2412 push(NullValue.FunctionBody); |
| 2358 } else { | 2413 } else { |
| 2359 push(new Block(<Statement>[new InvalidStatement()])); | 2414 push(new Block(<Statement>[new InvalidStatement()])); |
| 2360 } | 2415 } |
| 2361 } | 2416 } |
| 2362 | 2417 |
| 2363 @override | 2418 @override |
| 2419 void warning(String message, [int charOffset = -1]) { |
| 2420 if (constantExpressionRequired) { |
| 2421 addCompileTimeError(charOffset, message); |
| 2422 } else { |
| 2423 super.warning(message, charOffset); |
| 2424 } |
| 2425 } |
| 2426 |
| 2427 @override |
| 2364 void debugEvent(String name) { | 2428 void debugEvent(String name) { |
| 2365 // printEvent(name); | 2429 // printEvent(name); |
| 2366 } | 2430 } |
| 2367 } | 2431 } |
| 2368 | 2432 |
| 2369 // TODO(ahe): Shouldn't need to be an expression. | 2433 // TODO(ahe): Shouldn't need to be an expression. |
| 2370 class UnresolvedIdentifier extends InvalidExpression { | 2434 class UnresolvedIdentifier extends InvalidExpression { |
| 2371 final Name name; | 2435 final Name name; |
| 2372 | 2436 |
| 2373 UnresolvedIdentifier(this.name); | 2437 UnresolvedIdentifier(this.name); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2812 } else if (node is PrefixBuilder) { | 2876 } else if (node is PrefixBuilder) { |
| 2813 return node.name; | 2877 return node.name; |
| 2814 } else if (node is ThisAccessor) { | 2878 } else if (node is ThisAccessor) { |
| 2815 return node.isSuper ? "super" : "this"; | 2879 return node.isSuper ? "super" : "this"; |
| 2816 } else if (node is BuilderAccessor) { | 2880 } else if (node is BuilderAccessor) { |
| 2817 return node.plainNameForRead; | 2881 return node.plainNameForRead; |
| 2818 } else { | 2882 } else { |
| 2819 return internalError("Unhandled: ${node.runtimeType}"); | 2883 return internalError("Unhandled: ${node.runtimeType}"); |
| 2820 } | 2884 } |
| 2821 } | 2885 } |
| OLD | NEW |