| 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 |