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 |