| 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 'package:front_end/src/fasta/parser/parser.dart' show | 7 import 'package:front_end/src/fasta/parser/parser.dart' show |
| 8 FormalParameterType, | 8 FormalParameterType, |
| 9 optional; | 9 optional; |
| 10 | 10 |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 } | 273 } |
| 274 | 274 |
| 275 void exitSwitchScope() { | 275 void exitSwitchScope() { |
| 276 switchScope = pop(); | 276 switchScope = pop(); |
| 277 } | 277 } |
| 278 | 278 |
| 279 @override | 279 @override |
| 280 Uri get uri => library.fileUri ?? library.uri; | 280 Uri get uri => library.fileUri ?? library.uri; |
| 281 | 281 |
| 282 @override | 282 @override |
| 283 JumpTarget createJumpTarget(JumpTargetKind kind) => new JumpTarget(kind); | 283 JumpTarget createJumpTarget(JumpTargetKind kind, int charOffset) { |
| 284 return new JumpTarget(kind, member, charOffset); |
| 285 } |
| 284 | 286 |
| 285 @override | 287 @override |
| 286 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { | 288 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { |
| 287 debugEvent("Metadata"); | 289 debugEvent("Metadata"); |
| 288 pop(); // Arguments. | 290 pop(); // Arguments. |
| 289 popIfNotNull(periodBeforeName); // Postfix. | 291 popIfNotNull(periodBeforeName); // Postfix. |
| 290 pop(); // Type arguments. | 292 pop(); // Type arguments. |
| 291 pop(); // Expression or type name (depends on arguments). | 293 pop(); // Expression or type name (depends on arguments). |
| 292 // TODO(ahe): Implement metadata on local declarations. | 294 // TODO(ahe): Implement metadata on local declarations. |
| 293 } | 295 } |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 } | 701 } |
| 700 return null; | 702 return null; |
| 701 } | 703 } |
| 702 | 704 |
| 703 @override | 705 @override |
| 704 void beginExpression(Token token) { | 706 void beginExpression(Token token) { |
| 705 debugEvent("beginExpression"); | 707 debugEvent("beginExpression"); |
| 706 isFirstIdentifier = true; | 708 isFirstIdentifier = true; |
| 707 } | 709 } |
| 708 | 710 |
| 709 Builder computeSetter(Builder builder, Scope scope, String name) { | 711 Builder computeSetter( |
| 712 Builder builder, Scope scope, String name, int charOffset) { |
| 710 if (builder.isSetter) return builder; | 713 if (builder.isSetter) return builder; |
| 711 if (builder.isGetter) return scope.lookupSetter(name); | 714 if (builder.isGetter) return scope.lookupSetter(name, charOffset, uri); |
| 712 return builder.isField ? (builder.isFinal ? null : builder) : null; | 715 return builder.isField ? (builder.isFinal ? null : builder) : null; |
| 713 } | 716 } |
| 714 | 717 |
| 715 @override | 718 @override |
| 716 void handleIdentifier(Token token) { | 719 void handleIdentifier(Token token) { |
| 717 debugEvent("handleIdentifier"); | 720 debugEvent("handleIdentifier"); |
| 718 String name = token.value; | 721 String name = token.value; |
| 719 if (isFirstIdentifier) { | 722 if (isFirstIdentifier) { |
| 720 assert(!inInitializer || this.scope == enclosingScope || | 723 assert(!inInitializer || this.scope == enclosingScope || |
| 721 this.scope.parent == enclosingScope); | 724 this.scope.parent == enclosingScope); |
| 722 // This deals with this kind of initializer: `C(a) : a = a;` | 725 // This deals with this kind of initializer: `C(a) : a = a;` |
| 723 Scope scope = inInitializer ? enclosingScope : this.scope; | 726 Scope scope = inInitializer ? enclosingScope : this.scope; |
| 724 Builder builder = scope.lookup(name); | 727 Builder builder = scope.lookup(name, token.charOffset, uri); |
| 725 push(builderToFirstExpression(builder, name, token.charOffset)); | 728 push(builderToFirstExpression(builder, name, token.charOffset)); |
| 726 } else { | 729 } else { |
| 727 push(new Identifier(name)..fileOffset = token.charOffset); | 730 push(new Identifier(name)..fileOffset = token.charOffset); |
| 728 } | 731 } |
| 729 } | 732 } |
| 730 | 733 |
| 731 @override | 734 @override |
| 732 builderToFirstExpression(Builder builder, String name, int charOffset, | 735 builderToFirstExpression(Builder builder, String name, int charOffset, |
| 733 {bool isPrefix: false}) { | 736 {bool isPrefix: false}) { |
| 734 if (builder == null || (!isInstanceContext && builder.isInstanceMember)) { | 737 if (builder == null || (!isInstanceContext && builder.isInstanceMember)) { |
| 735 if (!isPrefix && identical(name, "dynamic") && builder == null) { | 738 if (!isPrefix && identical(name, "dynamic") && builder == null) { |
| 736 return new KernelNamedTypeBuilder(name, null); | 739 return new KernelNamedTypeBuilder(name, null, charOffset, uri); |
| 737 } | 740 } |
| 738 Name n = new Name(name, library.library); | 741 Name n = new Name(name, library.library); |
| 739 if (!isPrefix && isInstanceContext) { | 742 if (!isPrefix && isInstanceContext) { |
| 740 assert(builder == null); | 743 assert(builder == null); |
| 741 return new ThisPropertyAccessor(this, charOffset, n, null, null); | 744 return new ThisPropertyAccessor(this, charOffset, n, null, null); |
| 742 } else { | 745 } else { |
| 743 return new UnresolvedIdentifier(n) | 746 return new UnresolvedIdentifier(n) |
| 744 ..fileOffset = charOffset; | 747 ..fileOffset = charOffset; |
| 745 } | 748 } |
| 746 } else if (builder.isTypeDeclaration) { | 749 } else if (builder.isTypeDeclaration) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 761 } else { | 764 } else { |
| 762 if (builder is AccessErrorBuilder) { | 765 if (builder is AccessErrorBuilder) { |
| 763 AccessErrorBuilder error = builder; | 766 AccessErrorBuilder error = builder; |
| 764 builder = error.builder; | 767 builder = error.builder; |
| 765 } | 768 } |
| 766 if (builder.target == null) { | 769 if (builder.target == null) { |
| 767 return internalError("Unhandled: ${builder}"); | 770 return internalError("Unhandled: ${builder}"); |
| 768 } | 771 } |
| 769 Member getter = builder.target.hasGetter ? builder.target : null; | 772 Member getter = builder.target.hasGetter ? builder.target : null; |
| 770 Member setter = builder.target.hasSetter ? builder.target : null; | 773 Member setter = builder.target.hasSetter ? builder.target : null; |
| 771 setter ??= computeSetter(builder, scope, name)?.target; | 774 setter ??= computeSetter(builder, scope, name, charOffset)?.target; |
| 772 return | 775 return |
| 773 new StaticAccessor(this, charOffset, getter, setter); | 776 new StaticAccessor(this, charOffset, getter, setter); |
| 774 } | 777 } |
| 775 } | 778 } |
| 776 | 779 |
| 777 @override | 780 @override |
| 778 void handleQualified(Token period) { | 781 void handleQualified(Token period) { |
| 779 debugEvent("Qualified"); | 782 debugEvent("Qualified"); |
| 780 Identifier name = pop(); | 783 Identifier name = pop(); |
| 781 var receiver = pop(); | 784 var receiver = pop(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 TreeNode node = pop(); | 903 TreeNode node = pop(); |
| 901 VariableDeclaration variable; | 904 VariableDeclaration variable; |
| 902 if (node is VariableDeclaration) { | 905 if (node is VariableDeclaration) { |
| 903 variable = node; | 906 variable = node; |
| 904 } else if (node is Identifier) { | 907 } else if (node is Identifier) { |
| 905 variable = new VariableDeclaration(node.name); | 908 variable = new VariableDeclaration(node.name); |
| 906 } else { | 909 } else { |
| 907 internalError("unhandled identifier: ${node.runtimeType}"); | 910 internalError("unhandled identifier: ${node.runtimeType}"); |
| 908 } | 911 } |
| 909 push(variable); | 912 push(variable); |
| 910 scope[variable.name] = new KernelVariableBuilder(variable); | 913 scope[variable.name] = new KernelVariableBuilder(variable, |
| 914 // TODO(ahe): This should be `member ?? classBuilder ?? part`, but we |
| 915 // don't have an object representing the current part. |
| 916 member ?? classBuilder); |
| 911 } | 917 } |
| 912 | 918 |
| 913 @override | 919 @override |
| 914 void endVariablesDeclaration(int count, Token endToken) { | 920 void endVariablesDeclaration(int count, Token endToken) { |
| 915 debugEvent("VariablesDeclaration"); | 921 debugEvent("VariablesDeclaration"); |
| 916 List<VariableDeclaration> variables = popList(count); | 922 List<VariableDeclaration> variables = popList(count); |
| 917 DartType type = pop(); | 923 DartType type = pop(); |
| 918 int modifiers = Modifier.validate(pop()); | 924 int modifiers = Modifier.validate(pop()); |
| 919 bool isConst = (modifiers & constMask) != 0; | 925 bool isConst = (modifiers & constMask) != 0; |
| 920 bool isFinal = (modifiers & finalMask) != 0; | 926 bool isFinal = (modifiers & finalMask) != 0; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 new TypeLiteral(accessor.buildTypesWithBuiltArguments(null)))); | 958 new TypeLiteral(accessor.buildTypesWithBuiltArguments(null)))); |
| 953 } else if (accessor is! BuilderAccessor) { | 959 } else if (accessor is! BuilderAccessor) { |
| 954 push(buildCompileTimeError("Can't assign to this.", token.charOffset)); | 960 push(buildCompileTimeError("Can't assign to this.", token.charOffset)); |
| 955 } else { | 961 } else { |
| 956 push(new DelayedAssignment(this, token.charOffset, accessor, value, | 962 push(new DelayedAssignment(this, token.charOffset, accessor, value, |
| 957 token.stringValue)); | 963 token.stringValue)); |
| 958 } | 964 } |
| 959 } | 965 } |
| 960 | 966 |
| 961 @override | 967 @override |
| 962 void enterLoop() { | 968 void enterLoop(int charOffset) { |
| 963 if (peek() is LabelTarget) { | 969 if (peek() is LabelTarget) { |
| 964 LabelTarget target = peek(); | 970 LabelTarget target = peek(); |
| 965 enterBreakTarget(target.breakTarget); | 971 enterBreakTarget(charOffset, target.breakTarget); |
| 966 enterContinueTarget(target.continueTarget); | 972 enterContinueTarget(charOffset, target.continueTarget); |
| 967 } else{ | 973 } else{ |
| 968 enterBreakTarget(); | 974 enterBreakTarget(charOffset); |
| 969 enterContinueTarget(); | 975 enterContinueTarget(charOffset); |
| 970 } | 976 } |
| 971 } | 977 } |
| 972 | 978 |
| 973 void exitLoopOrSwitch(Statement statement) { | 979 void exitLoopOrSwitch(Statement statement) { |
| 974 if (compileTimeErrorInLoopOrSwitch != null) { | 980 if (compileTimeErrorInLoopOrSwitch != null) { |
| 975 push(compileTimeErrorInLoopOrSwitch); | 981 push(compileTimeErrorInLoopOrSwitch); |
| 976 compileTimeErrorInLoopOrSwitch = null; | 982 compileTimeErrorInLoopOrSwitch = null; |
| 977 } else { | 983 } else { |
| 978 push(statement); | 984 push(statement); |
| 979 } | 985 } |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 } else { | 1139 } else { |
| 1134 List parts = popList(identifierCount); | 1140 List parts = popList(identifierCount); |
| 1135 value = symbolPartToString(parts.first); | 1141 value = symbolPartToString(parts.first); |
| 1136 for (int i = 1; i < parts.length; i++) { | 1142 for (int i = 1; i < parts.length; i++) { |
| 1137 value += ".${symbolPartToString(parts[i])}"; | 1143 value += ".${symbolPartToString(parts[i])}"; |
| 1138 } | 1144 } |
| 1139 } | 1145 } |
| 1140 push(new SymbolLiteral(value)); | 1146 push(new SymbolLiteral(value)); |
| 1141 } | 1147 } |
| 1142 | 1148 |
| 1143 DartType toKernelType(String name, List<DartType> arguments) { | 1149 DartType toKernelType(String name, List<DartType> arguments, int charOffset) { |
| 1144 if (identical(name, "void")) return const VoidType(); | 1150 if (identical(name, "void")) return const VoidType(); |
| 1145 if (identical(name, "dynamic")) return const DynamicType(); | 1151 if (identical(name, "dynamic")) return const DynamicType(); |
| 1146 Builder builder = scope.lookup(name); | 1152 Builder builder = scope.lookup(name, charOffset, uri); |
| 1147 if (builder is TypeDeclarationBuilder) { | 1153 if (builder is TypeDeclarationBuilder) { |
| 1148 return builder.buildTypesWithBuiltArguments(arguments); | 1154 return builder.buildTypesWithBuiltArguments(arguments); |
| 1149 } | 1155 } |
| 1150 if (builder == null) { | 1156 if (builder == null) { |
| 1151 print("$uri: Type not found: $name"); | 1157 print("$uri: Type not found: $name"); |
| 1152 } else { | 1158 } else { |
| 1153 print("$uri: Not a type: $name"); | 1159 print("$uri: Not a type: $name"); |
| 1154 } | 1160 } |
| 1155 // TODO(ahe): Create an error somehow. | 1161 // TODO(ahe): Create an error somehow. |
| 1156 return const DynamicType(); | 1162 return const DynamicType(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1171 prefix = prefix.name; | 1177 prefix = prefix.name; |
| 1172 } | 1178 } |
| 1173 var suffix = name[1]; | 1179 var suffix = name[1]; |
| 1174 if (suffix is Identifier) { | 1180 if (suffix is Identifier) { |
| 1175 suffix = suffix.name; | 1181 suffix = suffix.name; |
| 1176 } | 1182 } |
| 1177 Builder builder; | 1183 Builder builder; |
| 1178 if (prefix is Builder) { | 1184 if (prefix is Builder) { |
| 1179 builder = prefix; | 1185 builder = prefix; |
| 1180 } else { | 1186 } else { |
| 1181 builder = scope.lookup(prefix); | 1187 builder = scope.lookup(prefix, beginToken.charOffset, uri); |
| 1182 } | 1188 } |
| 1183 if (builder is PrefixBuilder) { | 1189 if (builder is PrefixBuilder) { |
| 1184 name = builder.exports[suffix]; | 1190 name = builder.exports[suffix]; |
| 1185 } else { | 1191 } else { |
| 1186 return inputError( | 1192 return inputError( |
| 1187 "Can't be used as a type: '${debugName(prefix, suffix)}'.", | 1193 "Can't be used as a type: '${debugName(prefix, suffix)}'.", |
| 1188 beginToken.charOffset); | 1194 beginToken.charOffset); |
| 1189 } | 1195 } |
| 1190 } | 1196 } |
| 1191 if (name is Identifier) { | 1197 if (name is Identifier) { |
| 1192 name = name.name; | 1198 name = name.name; |
| 1193 } | 1199 } |
| 1194 if (name is BuilderAccessor) { | 1200 if (name is BuilderAccessor) { |
| 1195 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset); | 1201 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset); |
| 1196 push(const DynamicType()); | 1202 push(const DynamicType()); |
| 1197 } else if (name is UnresolvedIdentifier) { | 1203 } else if (name is UnresolvedIdentifier) { |
| 1198 warning("'${name.name}' isn't a type.", beginToken.charOffset); | 1204 warning("'${name.name}' isn't a type.", beginToken.charOffset); |
| 1199 push(const DynamicType()); | 1205 push(const DynamicType()); |
| 1200 } else if (name is TypeVariableBuilder) { | 1206 } else if (name is TypeVariableBuilder) { |
| 1201 push(name.buildTypesWithBuiltArguments(arguments)); | 1207 push(name.buildTypesWithBuiltArguments(arguments)); |
| 1202 } else if (name is TypeDeclarationBuilder) { | 1208 } else if (name is TypeDeclarationBuilder) { |
| 1203 push(name.buildTypesWithBuiltArguments(arguments)); | 1209 push(name.buildTypesWithBuiltArguments(arguments)); |
| 1204 } else if (name is TypeBuilder) { | 1210 } else if (name is TypeBuilder) { |
| 1205 push(name.build()); | 1211 push(name.build()); |
| 1206 } else { | 1212 } else { |
| 1207 push(toKernelType(name, arguments)); | 1213 push(toKernelType(name, arguments, beginToken.charOffset)); |
| 1208 } | 1214 } |
| 1209 if (peek() is TypeParameterType) { | 1215 if (peek() is TypeParameterType) { |
| 1210 TypeParameterType type = peek(); | 1216 TypeParameterType type = peek(); |
| 1211 if (!isInstanceContext && type.parameter.parent is Class) { | 1217 if (!isInstanceContext && type.parameter.parent is Class) { |
| 1212 pop(); | 1218 pop(); |
| 1213 warning("Type variables can only be used in instance methods.", | 1219 warning("Type variables can only be used in instance methods.", |
| 1214 beginToken.charOffset); | 1220 beginToken.charOffset); |
| 1215 push(const DynamicType()); | 1221 push(const DynamicType()); |
| 1216 } | 1222 } |
| 1217 } | 1223 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 @override | 1262 @override |
| 1257 void endThrowExpression(Token throwToken, Token endToken) { | 1263 void endThrowExpression(Token throwToken, Token endToken) { |
| 1258 debugEvent("ThrowExpression"); | 1264 debugEvent("ThrowExpression"); |
| 1259 Expression expression = popForValue(); | 1265 Expression expression = popForValue(); |
| 1260 push(new Throw(expression)); | 1266 push(new Throw(expression)); |
| 1261 } | 1267 } |
| 1262 | 1268 |
| 1263 @override | 1269 @override |
| 1264 void endFormalParameter(Token thisKeyword) { | 1270 void endFormalParameter(Token thisKeyword) { |
| 1265 debugEvent("FormalParameter"); | 1271 debugEvent("FormalParameter"); |
| 1272 // TODO(ahe): Need beginToken here. |
| 1273 int charOffset = thisKeyword?.charOffset; |
| 1266 if (thisKeyword != null) { | 1274 if (thisKeyword != null) { |
| 1267 if (!inConstructor) { | 1275 if (!inConstructor) { |
| 1268 return inputError("'this' parameters can only be used on constructors.", | 1276 return inputError("'this' parameters can only be used on constructors.", |
| 1269 thisKeyword.charOffset); | 1277 thisKeyword.charOffset); |
| 1270 } | 1278 } |
| 1271 } | 1279 } |
| 1272 Identifier name = pop(); | 1280 Identifier name = pop(); |
| 1273 DartType type = pop(); | 1281 DartType type = pop(); |
| 1274 pop(); // Modifiers. | 1282 pop(); // Modifiers. |
| 1275 ignore(Unhandled.Metadata); | 1283 ignore(Unhandled.Metadata); |
| 1276 VariableDeclaration variable; | 1284 VariableDeclaration variable; |
| 1277 if (!inCatchClause && functionNestingLevel == 0) { | 1285 if (!inCatchClause && functionNestingLevel == 0) { |
| 1278 var builder = formalParameterScope.lookup(name.name); | 1286 var builder = formalParameterScope.lookup(name.name, charOffset, uri); |
| 1279 if (builder == null) { | 1287 if (builder == null) { |
| 1280 return inputError("'${name.name}' isn't a field in this class.", | 1288 return inputError("'${name.name}' isn't a field in this class.", |
| 1281 name.fileOffset); | 1289 name.fileOffset); |
| 1282 } | 1290 } |
| 1283 if (thisKeyword == null) { | 1291 if (thisKeyword == null) { |
| 1284 variable = builder.build(); | 1292 variable = builder.build(); |
| 1285 variable.initializer = name.initializer; | 1293 variable.initializer = name.initializer; |
| 1286 } else if (builder.isField && builder.parent == classBuilder) { | 1294 } else if (builder.isField && builder.parent == classBuilder) { |
| 1287 FieldBuilder field = builder; | 1295 FieldBuilder field = builder; |
| 1288 if (type != null) { | 1296 if (type != null) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 debugEvent("FormalParameters"); | 1354 debugEvent("FormalParameters"); |
| 1347 OptionalFormals optional; | 1355 OptionalFormals optional; |
| 1348 if (count > 0 && peek() is OptionalFormals) { | 1356 if (count > 0 && peek() is OptionalFormals) { |
| 1349 optional = pop(); | 1357 optional = pop(); |
| 1350 count--; | 1358 count--; |
| 1351 } | 1359 } |
| 1352 FormalParameters formals = new FormalParameters( | 1360 FormalParameters formals = new FormalParameters( |
| 1353 popList(count) ?? <VariableDeclaration>[], optional); | 1361 popList(count) ?? <VariableDeclaration>[], optional); |
| 1354 push(formals); | 1362 push(formals); |
| 1355 if (inCatchClause || functionNestingLevel != 0) { | 1363 if (inCatchClause || functionNestingLevel != 0) { |
| 1356 enterLocalScope(formals.computeFormalParameterScope(scope)); | 1364 enterLocalScope(formals.computeFormalParameterScope( |
| 1365 scope, member ?? classBuilder ?? library)); |
| 1357 } | 1366 } |
| 1358 } | 1367 } |
| 1359 | 1368 |
| 1360 @override | 1369 @override |
| 1361 void beginCatchClause(Token token) { | 1370 void beginCatchClause(Token token) { |
| 1362 debugEvent("beginCatchClause"); | 1371 debugEvent("beginCatchClause"); |
| 1363 inCatchClause = true; | 1372 inCatchClause = true; |
| 1364 } | 1373 } |
| 1365 | 1374 |
| 1366 @override | 1375 @override |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1711 } | 1720 } |
| 1712 | 1721 |
| 1713 @override | 1722 @override |
| 1714 void endFunctionName(Token token) { | 1723 void endFunctionName(Token token) { |
| 1715 debugEvent("FunctionName"); | 1724 debugEvent("FunctionName"); |
| 1716 Identifier name = pop(); | 1725 Identifier name = pop(); |
| 1717 VariableDeclaration variable = new VariableDeclaration( | 1726 VariableDeclaration variable = new VariableDeclaration( |
| 1718 name.name, isFinal: true); | 1727 name.name, isFinal: true); |
| 1719 push(new FunctionDeclaration(variable, | 1728 push(new FunctionDeclaration(variable, |
| 1720 new FunctionNode(new InvalidStatement()))); | 1729 new FunctionNode(new InvalidStatement()))); |
| 1721 scope[variable.name] = new KernelVariableBuilder(variable); | 1730 scope[variable.name] = new KernelVariableBuilder(variable, |
| 1731 // TODO(ahe): This should be `member ?? classBuilder ?? part`, but we |
| 1732 // don't have an object representing the current part. |
| 1733 member ?? classBuilder); |
| 1722 enterLocalScope(); | 1734 enterLocalScope(); |
| 1723 } | 1735 } |
| 1724 | 1736 |
| 1725 @override | 1737 @override |
| 1726 void beginFunction(Token token) { | 1738 void beginFunction(Token token) { |
| 1727 debugEvent("beginFunction"); | 1739 debugEvent("beginFunction"); |
| 1728 functionNestingLevel++; | 1740 functionNestingLevel++; |
| 1729 } | 1741 } |
| 1730 | 1742 |
| 1731 @override | 1743 @override |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1861 debugEvent("Label"); | 1873 debugEvent("Label"); |
| 1862 Identifier identifier = pop(); | 1874 Identifier identifier = pop(); |
| 1863 push(new Label(identifier.name)); | 1875 push(new Label(identifier.name)); |
| 1864 } | 1876 } |
| 1865 | 1877 |
| 1866 @override | 1878 @override |
| 1867 void beginLabeledStatement(Token token, int labelCount) { | 1879 void beginLabeledStatement(Token token, int labelCount) { |
| 1868 debugEvent("beginLabeledStatement"); | 1880 debugEvent("beginLabeledStatement"); |
| 1869 List<Label> labels = popList(labelCount); | 1881 List<Label> labels = popList(labelCount); |
| 1870 enterLocalScope(); | 1882 enterLocalScope(); |
| 1871 LabelTarget target = new LabelTarget(); | 1883 LabelTarget target = new LabelTarget(member, token.charOffset); |
| 1872 for (Label label in labels) { | 1884 for (Label label in labels) { |
| 1873 scope[label.name] = target; | 1885 scope[label.name] = target; |
| 1874 } | 1886 } |
| 1875 push(target); | 1887 push(target); |
| 1876 } | 1888 } |
| 1877 | 1889 |
| 1878 @override | 1890 @override |
| 1879 void endLabeledStatement(int labelCount) { | 1891 void endLabeledStatement(int labelCount) { |
| 1880 debugEvent("LabeledStatement"); | 1892 debugEvent("LabeledStatement"); |
| 1881 Statement statement = popStatement(); | 1893 Statement statement = popStatement(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1946 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { | 1958 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { |
| 1947 debugEvent("YieldStatement"); | 1959 debugEvent("YieldStatement"); |
| 1948 push(new YieldStatement(popForValue(), isYieldStar: starToken != null)); | 1960 push(new YieldStatement(popForValue(), isYieldStar: starToken != null)); |
| 1949 } | 1961 } |
| 1950 | 1962 |
| 1951 @override | 1963 @override |
| 1952 void beginSwitchBlock(Token token) { | 1964 void beginSwitchBlock(Token token) { |
| 1953 debugEvent("beginSwitchBlock"); | 1965 debugEvent("beginSwitchBlock"); |
| 1954 enterLocalScope(); | 1966 enterLocalScope(); |
| 1955 enterSwitchScope(); | 1967 enterSwitchScope(); |
| 1956 enterBreakTarget(); | 1968 enterBreakTarget(token.charOffset); |
| 1957 } | 1969 } |
| 1958 | 1970 |
| 1959 @override | 1971 @override |
| 1960 void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) { | 1972 void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) { |
| 1961 debugEvent("beginSwitchCase"); | 1973 debugEvent("beginSwitchCase"); |
| 1962 List labelsAndExpressions = popList(labelCount + expressionCount); | 1974 List labelsAndExpressions = popList(labelCount + expressionCount); |
| 1963 List<Label> labels = <Label>[]; | 1975 List<Label> labels = <Label>[]; |
| 1964 List<Expression> expressions = <Expression>[]; | 1976 List<Expression> expressions = <Expression>[]; |
| 1965 if (labelsAndExpressions != null) { | 1977 if (labelsAndExpressions != null) { |
| 1966 for (var labelOrExpression in labelsAndExpressions) { | 1978 for (var labelOrExpression in labelsAndExpressions) { |
| 1967 if (labelOrExpression is Label) { | 1979 if (labelOrExpression is Label) { |
| 1968 labels.add(labelOrExpression); | 1980 labels.add(labelOrExpression); |
| 1969 } else { | 1981 } else { |
| 1970 expressions.add(toValue(labelOrExpression)); | 1982 expressions.add(toValue(labelOrExpression)); |
| 1971 } | 1983 } |
| 1972 } | 1984 } |
| 1973 } | 1985 } |
| 1974 assert(scope == switchScope); | 1986 assert(scope == switchScope); |
| 1975 for (Label label in labels) { | 1987 for (Label label in labels) { |
| 1976 Builder existing = scope.local[label.name]; | 1988 Builder existing = scope.local[label.name]; |
| 1977 if (existing == null) { | 1989 if (existing == null) { |
| 1978 scope[label.name] = createGotoTarget(); | 1990 scope[label.name] = createGotoTarget(firstToken.charOffset); |
| 1979 } else { | 1991 } else { |
| 1980 // TODO(ahe): Should validate this is a goto target and not duplicated. | 1992 // TODO(ahe): Should validate this is a goto target and not duplicated. |
| 1981 } | 1993 } |
| 1982 } | 1994 } |
| 1983 push(expressions); | 1995 push(expressions); |
| 1984 push(labels); | 1996 push(labels); |
| 1985 enterLocalScope(); | 1997 enterLocalScope(); |
| 1986 } | 1998 } |
| 1987 | 1999 |
| 1988 @override | 2000 @override |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2010 | 2022 |
| 2011 @override | 2023 @override |
| 2012 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | 2024 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { |
| 2013 debugEvent("SwitchBlock"); | 2025 debugEvent("SwitchBlock"); |
| 2014 List<SwitchCase> cases = | 2026 List<SwitchCase> cases = |
| 2015 new List<SwitchCase>.filled(caseCount, null, growable: true); | 2027 new List<SwitchCase>.filled(caseCount, null, growable: true); |
| 2016 for (int i = caseCount - 1; i >= 0; i--) { | 2028 for (int i = caseCount - 1; i >= 0; i--) { |
| 2017 List<Label> labels = pop(); | 2029 List<Label> labels = pop(); |
| 2018 SwitchCase current = cases[i] = pop(); | 2030 SwitchCase current = cases[i] = pop(); |
| 2019 for (Label label in labels) { | 2031 for (Label label in labels) { |
| 2020 JumpTarget target = switchScope.lookup(label.name); | 2032 JumpTarget target = |
| 2033 switchScope.lookup(label.name, label.fileOffset, uri); |
| 2021 if (target != null) { | 2034 if (target != null) { |
| 2022 target.resolveGotos(current); | 2035 target.resolveGotos(current); |
| 2023 } | 2036 } |
| 2024 } | 2037 } |
| 2025 // TODO(ahe): Validate that there's only one default and it's last. | 2038 // TODO(ahe): Validate that there's only one default and it's last. |
| 2026 } | 2039 } |
| 2027 JumpTarget target = exitBreakTarget(); | 2040 JumpTarget target = exitBreakTarget(); |
| 2028 exitSwitchScope(); | 2041 exitSwitchScope(); |
| 2029 exitLocalScope(); | 2042 exitLocalScope(); |
| 2030 Expression expression = popForValue(); | 2043 Expression expression = popForValue(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2044 | 2057 |
| 2045 @override | 2058 @override |
| 2046 void handleBreakStatement( | 2059 void handleBreakStatement( |
| 2047 bool hasTarget, Token breakKeyword, Token endToken) { | 2060 bool hasTarget, Token breakKeyword, Token endToken) { |
| 2048 debugEvent("BreakStatement"); | 2061 debugEvent("BreakStatement"); |
| 2049 var target = breakTarget; | 2062 var target = breakTarget; |
| 2050 String name; | 2063 String name; |
| 2051 if (hasTarget) { | 2064 if (hasTarget) { |
| 2052 Identifier identifier = pop(); | 2065 Identifier identifier = pop(); |
| 2053 name = identifier.name; | 2066 name = identifier.name; |
| 2054 target = scope.lookup(identifier.name); | 2067 target = scope.lookup( |
| 2068 identifier.name, breakKeyword.next.charOffset, uri); |
| 2055 } | 2069 } |
| 2056 if (target == null && name == null) { | 2070 if (target == null && name == null) { |
| 2057 push(compileTimeErrorInLoopOrSwitch = | 2071 push(compileTimeErrorInLoopOrSwitch = |
| 2058 buildCompileTimeErrorStatement( | 2072 buildCompileTimeErrorStatement( |
| 2059 "No target of break.", breakKeyword.charOffset)); | 2073 "No target of break.", breakKeyword.charOffset)); |
| 2060 } else if (target == null || target is! JumpTarget | 2074 } else if (target == null || target is! JumpTarget |
| 2061 || !target.isBreakTarget) { | 2075 || !target.isBreakTarget) { |
| 2062 push(compileTimeErrorInLoopOrSwitch = | 2076 push(compileTimeErrorInLoopOrSwitch = |
| 2063 buildCompileTimeErrorStatement("Can't break to '$name'.", | 2077 buildCompileTimeErrorStatement("Can't break to '$name'.", |
| 2064 breakKeyword.next.charOffset)); | 2078 breakKeyword.next.charOffset)); |
| 2065 } else { | 2079 } else { |
| 2066 BreakStatement statement = new BreakStatement(null); | 2080 BreakStatement statement = new BreakStatement(null); |
| 2067 target.addBreak(statement); | 2081 target.addBreak(statement); |
| 2068 push(statement); | 2082 push(statement); |
| 2069 } | 2083 } |
| 2070 } | 2084 } |
| 2071 | 2085 |
| 2072 @override | 2086 @override |
| 2073 void handleContinueStatement( | 2087 void handleContinueStatement( |
| 2074 bool hasTarget, Token continueKeyword, Token endToken) { | 2088 bool hasTarget, Token continueKeyword, Token endToken) { |
| 2075 debugEvent("ContinueStatement"); | 2089 debugEvent("ContinueStatement"); |
| 2076 var target = continueTarget; | 2090 var target = continueTarget; |
| 2077 String name; | 2091 String name; |
| 2078 if (hasTarget) { | 2092 if (hasTarget) { |
| 2079 Identifier identifier = pop(); | 2093 Identifier identifier = pop(); |
| 2080 name = identifier.name; | 2094 name = identifier.name; |
| 2081 target = scope.lookup(identifier.name); | 2095 target = scope.lookup( |
| 2096 identifier.name, continueKeyword.next.charOffset, uri); |
| 2082 if (target != null && target is! JumpTarget) { | 2097 if (target != null && target is! JumpTarget) { |
| 2083 push(compileTimeErrorInLoopOrSwitch = | 2098 push(compileTimeErrorInLoopOrSwitch = |
| 2084 buildCompileTimeErrorStatement( | 2099 buildCompileTimeErrorStatement( |
| 2085 "Target of continue must be a label.", | 2100 "Target of continue must be a label.", |
| 2086 continueKeyword.charOffset)); | 2101 continueKeyword.charOffset)); |
| 2087 return; | 2102 return; |
| 2088 } | 2103 } |
| 2089 if (target == null) { | 2104 if (target == null) { |
| 2090 if (switchScope == null) { | 2105 if (switchScope == null) { |
| 2091 push(buildCompileTimeErrorStatement("Can't find label '$name'.", | 2106 push(buildCompileTimeErrorStatement("Can't find label '$name'.", |
| 2092 continueKeyword.next.charOffset)); | 2107 continueKeyword.next.charOffset)); |
| 2093 return; | 2108 return; |
| 2094 } | 2109 } |
| 2095 switchScope[identifier.name] = target = createGotoTarget(); | 2110 switchScope[identifier.name] = target = |
| 2111 createGotoTarget(identifier.fileOffset); |
| 2096 } | 2112 } |
| 2097 if (target.isGotoTarget) { | 2113 if (target.isGotoTarget) { |
| 2098 ContinueSwitchStatement statement = new ContinueSwitchStatement(null); | 2114 ContinueSwitchStatement statement = new ContinueSwitchStatement(null); |
| 2099 target.addGoto(statement); | 2115 target.addGoto(statement); |
| 2100 push(statement); | 2116 push(statement); |
| 2101 return; | 2117 return; |
| 2102 } | 2118 } |
| 2103 } | 2119 } |
| 2104 if (target == null) { | 2120 if (target == null) { |
| 2105 push(compileTimeErrorInLoopOrSwitch = | 2121 push(compileTimeErrorInLoopOrSwitch = |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2478 return accessor.buildPostfixIncrement(binaryOperator, voidContext: true, | 2494 return accessor.buildPostfixIncrement(binaryOperator, voidContext: true, |
| 2479 interfaceTarget: interfaceTarget); | 2495 interfaceTarget: interfaceTarget); |
| 2480 } | 2496 } |
| 2481 } | 2497 } |
| 2482 | 2498 |
| 2483 class JumpTarget extends Builder { | 2499 class JumpTarget extends Builder { |
| 2484 final List<Statement> users = <Statement>[]; | 2500 final List<Statement> users = <Statement>[]; |
| 2485 | 2501 |
| 2486 final JumpTargetKind kind; | 2502 final JumpTargetKind kind; |
| 2487 | 2503 |
| 2488 JumpTarget(this.kind); | 2504 JumpTarget(this.kind, MemberBuilder member, int charOffset) |
| 2505 : super(member, charOffset, member.fileUri); |
| 2489 | 2506 |
| 2490 bool get isBreakTarget => kind == JumpTargetKind.Break; | 2507 bool get isBreakTarget => kind == JumpTargetKind.Break; |
| 2491 | 2508 |
| 2492 bool get isContinueTarget => kind == JumpTargetKind.Continue; | 2509 bool get isContinueTarget => kind == JumpTargetKind.Continue; |
| 2493 | 2510 |
| 2494 bool get isGotoTarget => kind == JumpTargetKind.Goto; | 2511 bool get isGotoTarget => kind == JumpTargetKind.Goto; |
| 2495 | 2512 |
| 2496 bool get hasUsers => users.isNotEmpty; | 2513 bool get hasUsers => users.isNotEmpty; |
| 2497 | 2514 |
| 2498 void addBreak(BreakStatement statement) { | 2515 void addBreak(BreakStatement statement) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2529 void resolveGotos(SwitchCase target) { | 2546 void resolveGotos(SwitchCase target) { |
| 2530 assert(isGotoTarget); | 2547 assert(isGotoTarget); |
| 2531 for (ContinueSwitchStatement user in users) { | 2548 for (ContinueSwitchStatement user in users) { |
| 2532 user.target = target; | 2549 user.target = target; |
| 2533 } | 2550 } |
| 2534 users.clear(); | 2551 users.clear(); |
| 2535 } | 2552 } |
| 2536 } | 2553 } |
| 2537 | 2554 |
| 2538 class LabelTarget extends Builder implements JumpTarget { | 2555 class LabelTarget extends Builder implements JumpTarget { |
| 2539 final JumpTarget breakTarget = new JumpTarget(JumpTargetKind.Break); | 2556 final JumpTarget breakTarget; |
| 2540 | 2557 |
| 2541 final JumpTarget continueTarget = new JumpTarget(JumpTargetKind.Continue); | 2558 final JumpTarget continueTarget; |
| 2542 | 2559 |
| 2543 LabelTarget(); | 2560 LabelTarget(MemberBuilder member, int charOffset) |
| 2561 : breakTarget = new JumpTarget(JumpTargetKind.Break, member, charOffset), |
| 2562 continueTarget = |
| 2563 new JumpTarget(JumpTargetKind.Continue, member, charOffset), |
| 2564 super(member, charOffset, member.fileUri); |
| 2544 | 2565 |
| 2545 bool get hasUsers => breakTarget.hasUsers || continueTarget.hasUsers; | 2566 bool get hasUsers => breakTarget.hasUsers || continueTarget.hasUsers; |
| 2546 | 2567 |
| 2547 List<Statement> get users => internalError("Unsupported operation."); | 2568 List<Statement> get users => internalError("Unsupported operation."); |
| 2548 | 2569 |
| 2549 JumpTargetKind get kind => internalError("Unsupported operation."); | 2570 JumpTargetKind get kind => internalError("Unsupported operation."); |
| 2550 | 2571 |
| 2551 bool get isBreakTarget => true; | 2572 bool get isBreakTarget => true; |
| 2552 | 2573 |
| 2553 bool get isContinueTarget => true; | 2574 bool get isContinueTarget => true; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2627 namedParameters.add(new NamedType(parameter.name, parameter.type)); | 2648 namedParameters.add(new NamedType(parameter.name, parameter.type)); |
| 2628 } | 2649 } |
| 2629 namedParameters.sort(); | 2650 namedParameters.sort(); |
| 2630 } | 2651 } |
| 2631 } | 2652 } |
| 2632 return new FunctionType(positionalParameters, returnType, | 2653 return new FunctionType(positionalParameters, returnType, |
| 2633 namedParameters: namedParameters, | 2654 namedParameters: namedParameters, |
| 2634 requiredParameterCount: requiredParameterCount); | 2655 requiredParameterCount: requiredParameterCount); |
| 2635 } | 2656 } |
| 2636 | 2657 |
| 2637 Scope computeFormalParameterScope(Scope parent) { | 2658 Scope computeFormalParameterScope(Scope parent, Builder builder) { |
| 2638 if (required.length == 0 && optional == null) return parent; | 2659 if (required.length == 0 && optional == null) return parent; |
| 2639 Map<String, Builder> local = <String, Builder>{}; | 2660 Map<String, Builder> local = <String, Builder>{}; |
| 2640 for (VariableDeclaration parameter in required) { | 2661 for (VariableDeclaration parameter in required) { |
| 2641 local[parameter.name] = new KernelVariableBuilder(parameter); | 2662 local[parameter.name] = new KernelVariableBuilder(parameter, builder); |
| 2642 } | 2663 } |
| 2643 if (optional != null) { | 2664 if (optional != null) { |
| 2644 for (VariableDeclaration parameter in optional.formals) { | 2665 for (VariableDeclaration parameter in optional.formals) { |
| 2645 local[parameter.name] = new KernelVariableBuilder(parameter); | 2666 local[parameter.name] = new KernelVariableBuilder(parameter, builder); |
| 2646 } | 2667 } |
| 2647 } | 2668 } |
| 2648 return new Scope(local, parent, isModifiable: false); | 2669 return new Scope(local, parent, isModifiable: false); |
| 2649 } | 2670 } |
| 2650 } | 2671 } |
| 2651 | 2672 |
| 2652 /// Returns a block like this: | 2673 /// Returns a block like this: |
| 2653 /// | 2674 /// |
| 2654 /// { | 2675 /// { |
| 2655 /// statement; | 2676 /// statement; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2680 } else if (node is TypeDeclarationBuilder) { | 2701 } else if (node is TypeDeclarationBuilder) { |
| 2681 return node.name; | 2702 return node.name; |
| 2682 } else if (node is PrefixBuilder) { | 2703 } else if (node is PrefixBuilder) { |
| 2683 return node.name; | 2704 return node.name; |
| 2684 } else if (node is ThisPropertyAccessor) { | 2705 } else if (node is ThisPropertyAccessor) { |
| 2685 return node.name.name; | 2706 return node.name.name; |
| 2686 } else { | 2707 } else { |
| 2687 return internalError("Unhandled: ${node.runtimeType}"); | 2708 return internalError("Unhandled: ${node.runtimeType}"); |
| 2688 } | 2709 } |
| 2689 } | 2710 } |
| OLD | NEW |