| 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, optional; | 10 import '../parser/parser.dart' show FormalParameterType, optional; |
| (...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 @override | 713 @override |
| 714 void handleIdentifier(Token token, IdentifierContext context) { | 714 void handleIdentifier(Token token, IdentifierContext context) { |
| 715 debugEvent("handleIdentifier"); | 715 debugEvent("handleIdentifier"); |
| 716 String name = token.lexeme; | 716 String name = token.lexeme; |
| 717 if (context.isScopeReference) { | 717 if (context.isScopeReference) { |
| 718 assert(!inInitializer || | 718 assert(!inInitializer || |
| 719 this.scope == enclosingScope || | 719 this.scope == enclosingScope || |
| 720 this.scope.parent == enclosingScope); | 720 this.scope.parent == enclosingScope); |
| 721 // This deals with this kind of initializer: `C(a) : a = a;` | 721 // This deals with this kind of initializer: `C(a) : a = a;` |
| 722 Scope scope = inInitializer ? enclosingScope : this.scope; | 722 Scope scope = inInitializer ? enclosingScope : this.scope; |
| 723 Builder builder = scope.lookup(name, token.charOffset, uri); | 723 push(scopeLookup(scope, name, token.charOffset)); |
| 724 push(builderToFirstExpression(builder, name, token.charOffset)); | |
| 725 return; | 724 return; |
| 726 } else if (context.inDeclaration) { | 725 } else if (context.inDeclaration) { |
| 727 if (context == IdentifierContext.topLevelVariableDeclaration || | 726 if (context == IdentifierContext.topLevelVariableDeclaration || |
| 728 context == IdentifierContext.fieldDeclaration) { | 727 context == IdentifierContext.fieldDeclaration) { |
| 729 constantExpressionRequired = member.isConst; | 728 constantExpressionRequired = member.isConst; |
| 730 } | 729 } |
| 731 } else if (constantExpressionRequired && | 730 } else if (constantExpressionRequired && |
| 732 !context.allowedInConstantExpression) { | 731 !context.allowedInConstantExpression) { |
| 733 addCompileTimeError( | 732 addCompileTimeError( |
| 734 token.charOffset, "Not a constant expression: $context"); | 733 token.charOffset, "Not a constant expression: $context"); |
| 735 } | 734 } |
| 736 push(new Identifier(name)..fileOffset = token.charOffset); | 735 push(new Identifier(name)..fileOffset = token.charOffset); |
| 737 } | 736 } |
| 738 | 737 |
| 738 /// Look up [name] in [scope] using [charOffset] to report any |
| 739 /// problems. [isQualified] should be true if [name] is a qualified access |
| 740 /// (which implies that it shouldn't be turned into a [ThisPropertyAccessor] |
| 741 /// if the name doesn't resolve in the scope). |
| 739 @override | 742 @override |
| 740 builderToFirstExpression(Builder builder, String name, int charOffset, | 743 scopeLookup(Scope scope, String name, int charOffset, |
| 741 {bool isPrefix: false}) { | 744 {bool isQualified: false}) { |
| 745 Builder builder = scope.lookup(name, charOffset, uri); |
| 742 if (builder == null || (!isInstanceContext && builder.isInstanceMember)) { | 746 if (builder == null || (!isInstanceContext && builder.isInstanceMember)) { |
| 743 Name n = new Name(name, library.library); | 747 Name n = new Name(name, library.library); |
| 744 if (!isPrefix && isInstanceContext) { | 748 if (!isQualified && isInstanceContext) { |
| 745 assert(builder == null); | 749 assert(builder == null); |
| 746 if (constantExpressionRequired) { | 750 if (constantExpressionRequired) { |
| 747 addCompileTimeError(charOffset, "Not a constant expression."); | 751 addCompileTimeError(charOffset, "Not a constant expression."); |
| 748 } | 752 } |
| 749 return new ThisPropertyAccessor(this, charOffset, n, null, null); | 753 return new ThisPropertyAccessor(this, charOffset, n, null, null); |
| 750 } else if (isDartLibrary && | 754 } else if (isDartLibrary && |
| 751 name == "main" && | 755 name == "main" && |
| 752 library.uri.path == "_builtin" && | 756 library.uri.path == "_builtin" && |
| 753 member?.name == "_getMainClosure") { | 757 member?.name == "_getMainClosure") { |
| 754 // TODO(ahe): https://github.com/dart-lang/sdk/issues/28989 | 758 // TODO(ahe): https://github.com/dart-lang/sdk/issues/28989 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 770 if (constantExpressionRequired) { | 774 if (constantExpressionRequired) { |
| 771 addCompileTimeError(charOffset, "Not a constant expression."); | 775 addCompileTimeError(charOffset, "Not a constant expression."); |
| 772 } | 776 } |
| 773 return new ThisPropertyAccessor( | 777 return new ThisPropertyAccessor( |
| 774 this, charOffset, new Name(name, library.library), null, null); | 778 this, charOffset, new Name(name, library.library), null, null); |
| 775 } else if (builder.isRegularMethod) { | 779 } else if (builder.isRegularMethod) { |
| 776 assert(builder.isStatic || builder.isTopLevel); | 780 assert(builder.isStatic || builder.isTopLevel); |
| 777 return new StaticAccessor(this, charOffset, builder.target, null); | 781 return new StaticAccessor(this, charOffset, builder.target, null); |
| 778 } else if (builder is PrefixBuilder) { | 782 } else if (builder is PrefixBuilder) { |
| 779 return builder; | 783 return builder; |
| 780 } else if (builder is MixedAccessor) { | |
| 781 if (constantExpressionRequired && !builder.getter.target.isConst) { | |
| 782 addCompileTimeError(charOffset, "Not a constant expression."); | |
| 783 } | |
| 784 return new StaticAccessor( | |
| 785 this, charOffset, builder.getter.target, builder.setter.target); | |
| 786 } else { | 784 } else { |
| 787 if (builder.hasProblem && builder is! AccessErrorBuilder) return builder; | 785 if (builder.hasProblem && builder is! AccessErrorBuilder) return builder; |
| 788 Builder setter; | 786 Builder setter; |
| 789 if (builder.isSetter) { | 787 if (builder.isSetter) { |
| 790 setter = builder; | 788 setter = builder; |
| 791 } else if (builder.isGetter) { | 789 } else if (builder.isGetter) { |
| 792 setter = scope.lookupSetter(name, charOffset, uri); | 790 setter = scope.lookupSetter(name, charOffset, uri); |
| 793 } else if (builder.isField && !builder.isFinal) { | 791 } else if (builder.isField && !builder.isFinal) { |
| 794 setter = builder; | 792 setter = builder; |
| 795 } | 793 } |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 if (suffix is Identifier) { | 1269 if (suffix is Identifier) { |
| 1272 suffix = suffix.name; | 1270 suffix = suffix.name; |
| 1273 } | 1271 } |
| 1274 Builder builder; | 1272 Builder builder; |
| 1275 if (prefix is Builder) { | 1273 if (prefix is Builder) { |
| 1276 builder = prefix; | 1274 builder = prefix; |
| 1277 } else { | 1275 } else { |
| 1278 builder = scope.lookup(prefix, beginToken.charOffset, uri); | 1276 builder = scope.lookup(prefix, beginToken.charOffset, uri); |
| 1279 } | 1277 } |
| 1280 if (builder is PrefixBuilder) { | 1278 if (builder is PrefixBuilder) { |
| 1281 name = builderToFirstExpression( | 1279 name = scopeLookup(builder.exports, suffix, beginToken.charOffset, |
| 1282 builder.exports[suffix], suffix, beginToken.charOffset, | 1280 isQualified: true); |
| 1283 isPrefix: true); | |
| 1284 } else { | 1281 } else { |
| 1285 push(const DynamicType()); | 1282 push(const DynamicType()); |
| 1286 addCompileTimeError(beginToken.charOffset, | 1283 addCompileTimeError(beginToken.charOffset, |
| 1287 "Can't be used as a type: '${debugName(prefix, suffix)}'."); | 1284 "Can't be used as a type: '${debugName(prefix, suffix)}'."); |
| 1288 return; | 1285 return; |
| 1289 } | 1286 } |
| 1290 } | 1287 } |
| 1291 if (name is Identifier) { | 1288 if (name is Identifier) { |
| 1292 name = name.name; | 1289 name = name.name; |
| 1293 } | 1290 } |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1649 // ClassBuilder, or a ThisPropertyAccessor. Otherwise, it's an error that | 1646 // ClassBuilder, or a ThisPropertyAccessor. Otherwise, it's an error that |
| 1650 // should be handled later. | 1647 // should be handled later. |
| 1651 Identifier suffix = popIfNotNull(periodBeforeName); | 1648 Identifier suffix = popIfNotNull(periodBeforeName); |
| 1652 Identifier identifier; | 1649 Identifier identifier; |
| 1653 List<DartType> typeArguments = pop(); | 1650 List<DartType> typeArguments = pop(); |
| 1654 dynamic type = pop(); | 1651 dynamic type = pop(); |
| 1655 if (type is List) { | 1652 if (type is List) { |
| 1656 var prefix = type[0]; | 1653 var prefix = type[0]; |
| 1657 identifier = type[1]; | 1654 identifier = type[1]; |
| 1658 if (prefix is PrefixBuilder) { | 1655 if (prefix is PrefixBuilder) { |
| 1659 // TODO(ahe): Handle privacy in prefix.exports. | 1656 type = scopeLookup(prefix.exports, identifier.name, start.charOffset, |
| 1660 type = builderToFirstExpression( | 1657 isQualified: true); |
| 1661 prefix.exports[identifier.name], identifier.name, start.charOffset); | |
| 1662 identifier = null; | 1658 identifier = null; |
| 1663 } else if (prefix is ClassBuilder) { | 1659 } else if (prefix is ClassBuilder) { |
| 1664 type = prefix; | 1660 type = prefix; |
| 1665 } else { | 1661 } else { |
| 1666 type = new Identifier(start.lexeme)..fileOffset = start.charOffset; | 1662 type = new Identifier(start.lexeme)..fileOffset = start.charOffset; |
| 1667 } | 1663 } |
| 1668 } | 1664 } |
| 1669 String name; | 1665 String name; |
| 1670 if (identifier != null && suffix != null) { | 1666 if (identifier != null && suffix != null) { |
| 1671 name = "${identifier.name}.${suffix.name}"; | 1667 name = "${identifier.name}.${suffix.name}"; |
| (...skipping 1227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2899 } else if (node is PrefixBuilder) { | 2895 } else if (node is PrefixBuilder) { |
| 2900 return node.name; | 2896 return node.name; |
| 2901 } else if (node is ThisAccessor) { | 2897 } else if (node is ThisAccessor) { |
| 2902 return node.isSuper ? "super" : "this"; | 2898 return node.isSuper ? "super" : "this"; |
| 2903 } else if (node is FastaAccessor) { | 2899 } else if (node is FastaAccessor) { |
| 2904 return node.plainNameForRead; | 2900 return node.plainNameForRead; |
| 2905 } else { | 2901 } else { |
| 2906 return internalError("Unhandled: ${node.runtimeType}"); | 2902 return internalError("Unhandled: ${node.runtimeType}"); |
| 2907 } | 2903 } |
| 2908 } | 2904 } |
| OLD | NEW |