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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 | 103 |
104 final Scope enclosingScope; | 104 final Scope enclosingScope; |
105 | 105 |
106 final bool isDartLibrary; | 106 final bool isDartLibrary; |
107 | 107 |
108 @override | 108 @override |
109 final Uri uri; | 109 final Uri uri; |
110 | 110 |
111 Scope formalParameterScope; | 111 Scope formalParameterScope; |
112 | 112 |
113 bool isFirstIdentifier = false; | |
114 | |
115 bool inInitializer = false; | 113 bool inInitializer = false; |
116 | 114 |
117 bool inCatchClause = false; | 115 bool inCatchClause = false; |
118 | 116 |
119 int functionNestingLevel = 0; | 117 int functionNestingLevel = 0; |
120 | 118 |
121 Statement compileTimeErrorInTry; | 119 Statement compileTimeErrorInTry; |
122 | 120 |
123 Statement compileTimeErrorInLoopOrSwitch; | 121 Statement compileTimeErrorInLoopOrSwitch; |
124 | 122 |
(...skipping 21 matching lines...) Expand all Loading... |
146 bool get inConstructor { | 144 bool get inConstructor { |
147 return functionNestingLevel == 0 && member is KernelConstructorBuilder; | 145 return functionNestingLevel == 0 && member is KernelConstructorBuilder; |
148 } | 146 } |
149 | 147 |
150 bool get isInstanceContext { | 148 bool get isInstanceContext { |
151 return isInstanceMember || member is KernelConstructorBuilder; | 149 return isInstanceMember || member is KernelConstructorBuilder; |
152 } | 150 } |
153 | 151 |
154 @override | 152 @override |
155 void push(Object node) { | 153 void push(Object node) { |
156 isFirstIdentifier = false; | |
157 inInitializer = false; | 154 inInitializer = false; |
158 super.push(node); | 155 super.push(node); |
159 } | 156 } |
160 | 157 |
161 Expression popForValue() => toValue(pop()); | 158 Expression popForValue() => toValue(pop()); |
162 | 159 |
163 Expression popForEffect() => toEffect(pop()); | 160 Expression popForEffect() => toEffect(pop()); |
164 | 161 |
165 Expression popForValueIfNotNull(Object value) { | 162 Expression popForValueIfNotNull(Object value) { |
166 return value == null ? null : popForValue(); | 163 return value == null ? null : popForValue(); |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 } | 705 } |
709 if (cls != null) { | 706 if (cls != null) { |
710 for (Constructor constructor in cls.constructors) { | 707 for (Constructor constructor in cls.constructors) { |
711 if (constructor.name == name) return constructor; | 708 if (constructor.name == name) return constructor; |
712 } | 709 } |
713 } | 710 } |
714 return null; | 711 return null; |
715 } | 712 } |
716 | 713 |
717 @override | 714 @override |
718 void beginExpression(Token token) { | |
719 debugEvent("beginExpression"); | |
720 isFirstIdentifier = true; | |
721 } | |
722 | |
723 @override | |
724 void handleIdentifier(Token token, IdentifierContext context) { | 715 void handleIdentifier(Token token, IdentifierContext context) { |
725 debugEvent("handleIdentifier"); | 716 debugEvent("handleIdentifier"); |
726 String name = token.lexeme; | 717 String name = token.lexeme; |
727 if (isFirstIdentifier) { | 718 if (context.isScopeReference) { |
728 assert(!inInitializer || | 719 assert(!inInitializer || |
729 this.scope == enclosingScope || | 720 this.scope == enclosingScope || |
730 this.scope.parent == enclosingScope); | 721 this.scope.parent == enclosingScope); |
731 // This deals with this kind of initializer: `C(a) : a = a;` | 722 // This deals with this kind of initializer: `C(a) : a = a;` |
732 Scope scope = inInitializer ? enclosingScope : this.scope; | 723 Scope scope = inInitializer ? enclosingScope : this.scope; |
733 Builder builder = scope.lookup(name, token.charOffset, uri); | 724 Builder builder = scope.lookup(name, token.charOffset, uri); |
734 push(builderToFirstExpression(builder, name, token.charOffset)); | 725 push(builderToFirstExpression(builder, name, token.charOffset)); |
735 } else { | 726 } else { |
736 push(new Identifier(name)..fileOffset = token.charOffset); | 727 push(new Identifier(name)..fileOffset = token.charOffset); |
737 } | 728 } |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 } | 1134 } |
1144 | 1135 |
1145 @override | 1136 @override |
1146 void endLiteralMapEntry(Token colon, Token endToken) { | 1137 void endLiteralMapEntry(Token colon, Token endToken) { |
1147 debugEvent("LiteralMapEntry"); | 1138 debugEvent("LiteralMapEntry"); |
1148 Expression value = popForValue(); | 1139 Expression value = popForValue(); |
1149 Expression key = popForValue(); | 1140 Expression key = popForValue(); |
1150 push(new MapEntry(key, value)); | 1141 push(new MapEntry(key, value)); |
1151 } | 1142 } |
1152 | 1143 |
1153 @override | |
1154 void beginLiteralSymbol(Token token) { | |
1155 isFirstIdentifier = false; | |
1156 } | |
1157 | |
1158 String symbolPartToString(name) { | 1144 String symbolPartToString(name) { |
1159 if (name is Identifier) { | 1145 if (name is Identifier) { |
1160 return name.name; | 1146 return name.name; |
1161 } else if (name is Operator) { | 1147 } else if (name is Operator) { |
1162 return name.name; | 1148 return name.name; |
1163 } else { | 1149 } else { |
1164 return internalError("Unhandled: ${name.runtimeType}"); | 1150 return internalError("Unhandled: ${name.runtimeType}"); |
1165 } | 1151 } |
1166 } | 1152 } |
1167 | 1153 |
1168 @override | 1154 @override |
1169 void endLiteralSymbol(Token hashToken, int identifierCount) { | 1155 void endLiteralSymbol(Token hashToken, int identifierCount) { |
1170 debugEvent("LiteralSymbol"); | 1156 debugEvent("LiteralSymbol"); |
1171 String value; | 1157 String value; |
1172 if (identifierCount == 1) { | 1158 if (identifierCount == 1) { |
1173 value = symbolPartToString(popForValue()); | 1159 value = symbolPartToString(popForValue()); |
1174 } else { | 1160 } else { |
1175 List parts = popList(identifierCount); | 1161 List parts = popList(identifierCount); |
1176 value = symbolPartToString(parts.first); | 1162 value = symbolPartToString(parts.first); |
1177 for (int i = 1; i < parts.length; i++) { | 1163 for (int i = 1; i < parts.length; i++) { |
1178 value += ".${symbolPartToString(parts[i])}"; | 1164 value += ".${symbolPartToString(parts[i])}"; |
1179 } | 1165 } |
1180 } | 1166 } |
1181 push(new SymbolLiteral(value)); | 1167 push(new SymbolLiteral(value)); |
1182 } | 1168 } |
1183 | 1169 |
1184 DartType toKernelType(String name, List<DartType> arguments, int charOffset) { | 1170 DartType kernelTypeFromString( |
| 1171 String name, List<DartType> arguments, int charOffset) { |
1185 Builder builder = scope.lookup(name, charOffset, uri); | 1172 Builder builder = scope.lookup(name, charOffset, uri); |
| 1173 if (builder == null) { |
| 1174 warning("Type not found: '$name'.", charOffset); |
| 1175 return const DynamicType(); |
| 1176 } else { |
| 1177 return kernelTypeFromBuilder(builder, arguments, charOffset); |
| 1178 } |
| 1179 } |
| 1180 |
| 1181 DartType kernelTypeFromBuilder( |
| 1182 Builder builder, List<DartType> arguments, int charOffset) { |
1186 if (builder is TypeDeclarationBuilder) { | 1183 if (builder is TypeDeclarationBuilder) { |
1187 return builder.buildTypesWithBuiltArguments(library, arguments); | 1184 return builder.buildTypesWithBuiltArguments(library, arguments); |
1188 } | 1185 } else if (builder.hasProblem) { |
1189 if (builder == null) { | 1186 ProblemBuilder problem = builder; |
1190 warning("Type not found: '$name'.", charOffset); | 1187 addCompileTimeError(charOffset, problem.message); |
1191 } else { | 1188 } else { |
1192 warning("Not a type: '$name'.", charOffset); | 1189 warning("Not a type: '${builder.fullNameForErrors}'.", charOffset); |
1193 } | 1190 } |
1194 // TODO(ahe): Create an error somehow. | 1191 // TODO(ahe): Create an error somehow. |
1195 return const DynamicType(); | 1192 return const DynamicType(); |
1196 } | 1193 } |
1197 | 1194 |
1198 @override | 1195 @override |
1199 void handleType(Token beginToken, Token endToken) { | 1196 void handleType(Token beginToken, Token endToken) { |
1200 // TODO(ahe): The scope is wrong for return types of generic functions. | 1197 // TODO(ahe): The scope is wrong for return types of generic functions. |
1201 debugEvent("Type"); | 1198 debugEvent("Type"); |
1202 List<DartType> arguments = pop(); | 1199 List<DartType> arguments = pop(); |
(...skipping 10 matching lines...) Expand all Loading... |
1213 if (suffix is Identifier) { | 1210 if (suffix is Identifier) { |
1214 suffix = suffix.name; | 1211 suffix = suffix.name; |
1215 } | 1212 } |
1216 Builder builder; | 1213 Builder builder; |
1217 if (prefix is Builder) { | 1214 if (prefix is Builder) { |
1218 builder = prefix; | 1215 builder = prefix; |
1219 } else { | 1216 } else { |
1220 builder = scope.lookup(prefix, beginToken.charOffset, uri); | 1217 builder = scope.lookup(prefix, beginToken.charOffset, uri); |
1221 } | 1218 } |
1222 if (builder is PrefixBuilder) { | 1219 if (builder is PrefixBuilder) { |
1223 name = builder.exports[suffix]; | 1220 name = builderToFirstExpression( |
| 1221 builder.exports[suffix], suffix, beginToken.charOffset, |
| 1222 isPrefix: true); |
1224 } else { | 1223 } else { |
1225 push(const DynamicType()); | 1224 push(const DynamicType()); |
1226 addCompileTimeError(beginToken.charOffset, | 1225 addCompileTimeError(beginToken.charOffset, |
1227 "Can't be used as a type: '${debugName(prefix, suffix)}'."); | 1226 "Can't be used as a type: '${debugName(prefix, suffix)}'."); |
1228 return; | 1227 return; |
1229 } | 1228 } |
1230 } | 1229 } |
1231 if (name is Identifier) { | 1230 if (name is Identifier) { |
1232 name = name.name; | 1231 name = name.name; |
1233 } | 1232 } |
1234 if (name is BuilderAccessor) { | 1233 if (name is BuilderAccessor) { |
1235 warning("'${beginToken.lexeme}' isn't a type.", beginToken.charOffset); | 1234 warning("'${beginToken.lexeme}' isn't a type.", beginToken.charOffset); |
1236 push(const DynamicType()); | 1235 push(const DynamicType()); |
1237 } else if (name is UnresolvedIdentifier) { | 1236 } else if (name is UnresolvedIdentifier) { |
1238 warning("'${name.name}' isn't a type.", beginToken.charOffset); | 1237 warning("'${name.name}' isn't a type.", beginToken.charOffset); |
1239 push(const DynamicType()); | 1238 push(const DynamicType()); |
1240 } else if (name is TypeVariableBuilder) { | 1239 } else if (name is TypeVariableBuilder) { |
1241 push(name.buildTypesWithBuiltArguments(library, arguments)); | 1240 push(name.buildTypesWithBuiltArguments(library, arguments)); |
1242 } else if (name is TypeDeclarationBuilder) { | 1241 } else if (name is TypeDeclarationBuilder) { |
1243 push(name.buildTypesWithBuiltArguments(library, arguments)); | 1242 push(name.buildTypesWithBuiltArguments(library, arguments)); |
1244 } else if (name is TypeBuilder) { | 1243 } else if (name is TypeBuilder) { |
1245 push(name.build(library)); | 1244 push(name.build(library)); |
| 1245 } else if (name is Builder) { |
| 1246 push(kernelTypeFromBuilder(name, arguments, beginToken.charOffset)); |
| 1247 } else if (name is String) { |
| 1248 push(kernelTypeFromString(name, arguments, beginToken.charOffset)); |
1246 } else { | 1249 } else { |
1247 push(toKernelType(name, arguments, beginToken.charOffset)); | 1250 internalError("Unhandled: '${name.runtimeType}'."); |
1248 } | 1251 } |
1249 if (peek() is TypeParameterType) { | 1252 if (peek() is TypeParameterType) { |
1250 TypeParameterType type = peek(); | 1253 TypeParameterType type = peek(); |
1251 if (!isInstanceContext && type.parameter.parent is Class) { | 1254 if (!isInstanceContext && type.parameter.parent is Class) { |
1252 pop(); | 1255 pop(); |
1253 warning("Type variables can only be used in instance methods.", | 1256 warning("Type variables can only be used in instance methods.", |
1254 beginToken.charOffset); | 1257 beginToken.charOffset); |
1255 push(const DynamicType()); | 1258 push(const DynamicType()); |
1256 } | 1259 } |
1257 } | 1260 } |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1714 | 1717 |
1715 @override | 1718 @override |
1716 void endTypeArguments(int count, Token beginToken, Token endToken) { | 1719 void endTypeArguments(int count, Token beginToken, Token endToken) { |
1717 debugEvent("TypeArguments"); | 1720 debugEvent("TypeArguments"); |
1718 push(popList(count)); | 1721 push(popList(count)); |
1719 } | 1722 } |
1720 | 1723 |
1721 @override | 1724 @override |
1722 void handleThisExpression(Token token, IdentifierContext context) { | 1725 void handleThisExpression(Token token, IdentifierContext context) { |
1723 debugEvent("ThisExpression"); | 1726 debugEvent("ThisExpression"); |
1724 if (isFirstIdentifier && isInstanceContext) { | 1727 if (context.isScopeReference && isInstanceContext) { |
1725 push(new ThisAccessor(this, token.charOffset, inInitializer)); | 1728 push(new ThisAccessor(this, token.charOffset, inInitializer)); |
1726 } else { | 1729 } else { |
1727 push(new IncompleteError( | 1730 push(new IncompleteError( |
1728 this, token.charOffset, "Expected identifier, but got 'this'.")); | 1731 this, token.charOffset, "Expected identifier, but got 'this'.")); |
1729 } | 1732 } |
1730 } | 1733 } |
1731 | 1734 |
1732 @override | 1735 @override |
1733 void handleSuperExpression(Token token, IdentifierContext context) { | 1736 void handleSuperExpression(Token token, IdentifierContext context) { |
1734 debugEvent("SuperExpression"); | 1737 debugEvent("SuperExpression"); |
1735 if (isFirstIdentifier && isInstanceContext) { | 1738 if (context.isScopeReference && isInstanceContext) { |
1736 Member member = this.member.target; | 1739 Member member = this.member.target; |
1737 member.transformerFlags |= TransformerFlag.superCalls; | 1740 member.transformerFlags |= TransformerFlag.superCalls; |
1738 push(new ThisAccessor(this, token.charOffset, inInitializer, | 1741 push(new ThisAccessor(this, token.charOffset, inInitializer, |
1739 isSuper: true)); | 1742 isSuper: true)); |
1740 } else { | 1743 } else { |
1741 push(new IncompleteError( | 1744 push(new IncompleteError( |
1742 this, token.charOffset, "Expected identifier, but got 'super'.")); | 1745 this, token.charOffset, "Expected identifier, but got 'super'.")); |
1743 } | 1746 } |
1744 } | 1747 } |
1745 | 1748 |
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2736 } else if (node is PrefixBuilder) { | 2739 } else if (node is PrefixBuilder) { |
2737 return node.name; | 2740 return node.name; |
2738 } else if (node is ThisAccessor) { | 2741 } else if (node is ThisAccessor) { |
2739 return node.isSuper ? "super" : "this"; | 2742 return node.isSuper ? "super" : "this"; |
2740 } else if (node is BuilderAccessor) { | 2743 } else if (node is BuilderAccessor) { |
2741 return node.plainNameForRead; | 2744 return node.plainNameForRead; |
2742 } else { | 2745 } else { |
2743 return internalError("Unhandled: ${node.runtimeType}"); | 2746 return internalError("Unhandled: ${node.runtimeType}"); |
2744 } | 2747 } |
2745 } | 2748 } |
OLD | NEW |