Chromium Code Reviews| 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] = |
| 914 new KernelVariableBuilder(variable, member ?? classBuilder); | |
|
Johnni Winther
2017/02/13 08:42:03
Should it be `member ?? classBuilder ?? library` ?
ahe
2017/02/13 10:44:23
I've added a TODO. It should be the current part,
| |
| 911 } | 915 } |
| 912 | 916 |
| 913 @override | 917 @override |
| 914 void endVariablesDeclaration(int count, Token endToken) { | 918 void endVariablesDeclaration(int count, Token endToken) { |
| 915 debugEvent("VariablesDeclaration"); | 919 debugEvent("VariablesDeclaration"); |
| 916 List<VariableDeclaration> variables = popList(count); | 920 List<VariableDeclaration> variables = popList(count); |
| 917 DartType type = pop(); | 921 DartType type = pop(); |
| 918 int modifiers = Modifier.validate(pop()); | 922 int modifiers = Modifier.validate(pop()); |
| 919 bool isConst = (modifiers & constMask) != 0; | 923 bool isConst = (modifiers & constMask) != 0; |
| 920 bool isFinal = (modifiers & finalMask) != 0; | 924 bool isFinal = (modifiers & finalMask) != 0; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 952 new TypeLiteral(accessor.buildTypesWithBuiltArguments(null)))); | 956 new TypeLiteral(accessor.buildTypesWithBuiltArguments(null)))); |
| 953 } else if (accessor is! BuilderAccessor) { | 957 } else if (accessor is! BuilderAccessor) { |
| 954 push(buildCompileTimeError("Can't assign to this.", token.charOffset)); | 958 push(buildCompileTimeError("Can't assign to this.", token.charOffset)); |
| 955 } else { | 959 } else { |
| 956 push(new DelayedAssignment(this, token.charOffset, accessor, value, | 960 push(new DelayedAssignment(this, token.charOffset, accessor, value, |
| 957 token.stringValue)); | 961 token.stringValue)); |
| 958 } | 962 } |
| 959 } | 963 } |
| 960 | 964 |
| 961 @override | 965 @override |
| 962 void enterLoop() { | 966 void enterLoop(int charOffset) { |
| 963 if (peek() is LabelTarget) { | 967 if (peek() is LabelTarget) { |
| 964 LabelTarget target = peek(); | 968 LabelTarget target = peek(); |
| 965 enterBreakTarget(target.breakTarget); | 969 enterBreakTarget(charOffset, target.breakTarget); |
| 966 enterContinueTarget(target.continueTarget); | 970 enterContinueTarget(charOffset, target.continueTarget); |
| 967 } else{ | 971 } else{ |
| 968 enterBreakTarget(); | 972 enterBreakTarget(charOffset); |
| 969 enterContinueTarget(); | 973 enterContinueTarget(charOffset); |
| 970 } | 974 } |
| 971 } | 975 } |
| 972 | 976 |
| 973 void exitLoopOrSwitch(Statement statement) { | 977 void exitLoopOrSwitch(Statement statement) { |
| 974 if (compileTimeErrorInLoopOrSwitch != null) { | 978 if (compileTimeErrorInLoopOrSwitch != null) { |
| 975 push(compileTimeErrorInLoopOrSwitch); | 979 push(compileTimeErrorInLoopOrSwitch); |
| 976 compileTimeErrorInLoopOrSwitch = null; | 980 compileTimeErrorInLoopOrSwitch = null; |
| 977 } else { | 981 } else { |
| 978 push(statement); | 982 push(statement); |
| 979 } | 983 } |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1133 } else { | 1137 } else { |
| 1134 List parts = popList(identifierCount); | 1138 List parts = popList(identifierCount); |
| 1135 value = symbolPartToString(parts.first); | 1139 value = symbolPartToString(parts.first); |
| 1136 for (int i = 1; i < parts.length; i++) { | 1140 for (int i = 1; i < parts.length; i++) { |
| 1137 value += ".${symbolPartToString(parts[i])}"; | 1141 value += ".${symbolPartToString(parts[i])}"; |
| 1138 } | 1142 } |
| 1139 } | 1143 } |
| 1140 push(new SymbolLiteral(value)); | 1144 push(new SymbolLiteral(value)); |
| 1141 } | 1145 } |
| 1142 | 1146 |
| 1143 DartType toKernelType(String name, List<DartType> arguments) { | 1147 DartType toKernelType(String name, List<DartType> arguments, int charOffset) { |
| 1144 if (identical(name, "void")) return const VoidType(); | 1148 if (identical(name, "void")) return const VoidType(); |
| 1145 if (identical(name, "dynamic")) return const DynamicType(); | 1149 if (identical(name, "dynamic")) return const DynamicType(); |
| 1146 Builder builder = scope.lookup(name); | 1150 Builder builder = scope.lookup(name, charOffset, uri); |
| 1147 if (builder is TypeDeclarationBuilder) { | 1151 if (builder is TypeDeclarationBuilder) { |
| 1148 return builder.buildTypesWithBuiltArguments(arguments); | 1152 return builder.buildTypesWithBuiltArguments(arguments); |
| 1149 } | 1153 } |
| 1150 if (builder == null) { | 1154 if (builder == null) { |
| 1151 print("$uri: Type not found: $name"); | 1155 print("$uri: Type not found: $name"); |
| 1152 } else { | 1156 } else { |
| 1153 print("$uri: Not a type: $name"); | 1157 print("$uri: Not a type: $name"); |
| 1154 } | 1158 } |
| 1155 // TODO(ahe): Create an error somehow. | 1159 // TODO(ahe): Create an error somehow. |
| 1156 return const DynamicType(); | 1160 return const DynamicType(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1171 prefix = prefix.name; | 1175 prefix = prefix.name; |
| 1172 } | 1176 } |
| 1173 var suffix = name[1]; | 1177 var suffix = name[1]; |
| 1174 if (suffix is Identifier) { | 1178 if (suffix is Identifier) { |
| 1175 suffix = suffix.name; | 1179 suffix = suffix.name; |
| 1176 } | 1180 } |
| 1177 Builder builder; | 1181 Builder builder; |
| 1178 if (prefix is Builder) { | 1182 if (prefix is Builder) { |
| 1179 builder = prefix; | 1183 builder = prefix; |
| 1180 } else { | 1184 } else { |
| 1181 builder = scope.lookup(prefix); | 1185 builder = scope.lookup(prefix, beginToken.charOffset, uri); |
| 1182 } | 1186 } |
| 1183 if (builder is PrefixBuilder) { | 1187 if (builder is PrefixBuilder) { |
| 1184 name = builder.exports[suffix]; | 1188 name = builder.exports[suffix]; |
| 1185 } else { | 1189 } else { |
| 1186 return inputError( | 1190 return inputError( |
| 1187 "Can't be used as a type: '${debugName(prefix, suffix)}'.", | 1191 "Can't be used as a type: '${debugName(prefix, suffix)}'.", |
| 1188 beginToken.charOffset); | 1192 beginToken.charOffset); |
| 1189 } | 1193 } |
| 1190 } | 1194 } |
| 1191 if (name is Identifier) { | 1195 if (name is Identifier) { |
| 1192 name = name.name; | 1196 name = name.name; |
| 1193 } | 1197 } |
| 1194 if (name is BuilderAccessor) { | 1198 if (name is BuilderAccessor) { |
| 1195 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset); | 1199 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset); |
| 1196 push(const DynamicType()); | 1200 push(const DynamicType()); |
| 1197 } else if (name is UnresolvedIdentifier) { | 1201 } else if (name is UnresolvedIdentifier) { |
| 1198 warning("'${name.name}' isn't a type.", beginToken.charOffset); | 1202 warning("'${name.name}' isn't a type.", beginToken.charOffset); |
| 1199 push(const DynamicType()); | 1203 push(const DynamicType()); |
| 1200 } else if (name is TypeVariableBuilder) { | 1204 } else if (name is TypeVariableBuilder) { |
| 1201 push(name.buildTypesWithBuiltArguments(arguments)); | 1205 push(name.buildTypesWithBuiltArguments(arguments)); |
| 1202 } else if (name is TypeDeclarationBuilder) { | 1206 } else if (name is TypeDeclarationBuilder) { |
| 1203 push(name.buildTypesWithBuiltArguments(arguments)); | 1207 push(name.buildTypesWithBuiltArguments(arguments)); |
| 1204 } else if (name is TypeBuilder) { | 1208 } else if (name is TypeBuilder) { |
| 1205 push(name.build()); | 1209 push(name.build()); |
| 1206 } else { | 1210 } else { |
| 1207 push(toKernelType(name, arguments)); | 1211 push(toKernelType(name, arguments, beginToken.charOffset)); |
| 1208 } | 1212 } |
| 1209 if (peek() is TypeParameterType) { | 1213 if (peek() is TypeParameterType) { |
| 1210 TypeParameterType type = peek(); | 1214 TypeParameterType type = peek(); |
| 1211 if (!isInstanceContext && type.parameter.parent is Class) { | 1215 if (!isInstanceContext && type.parameter.parent is Class) { |
| 1212 pop(); | 1216 pop(); |
| 1213 warning("Type variables can only be used in instance methods.", | 1217 warning("Type variables can only be used in instance methods.", |
| 1214 beginToken.charOffset); | 1218 beginToken.charOffset); |
| 1215 push(const DynamicType()); | 1219 push(const DynamicType()); |
| 1216 } | 1220 } |
| 1217 } | 1221 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1256 @override | 1260 @override |
| 1257 void endThrowExpression(Token throwToken, Token endToken) { | 1261 void endThrowExpression(Token throwToken, Token endToken) { |
| 1258 debugEvent("ThrowExpression"); | 1262 debugEvent("ThrowExpression"); |
| 1259 Expression expression = popForValue(); | 1263 Expression expression = popForValue(); |
| 1260 push(new Throw(expression)); | 1264 push(new Throw(expression)); |
| 1261 } | 1265 } |
| 1262 | 1266 |
| 1263 @override | 1267 @override |
| 1264 void endFormalParameter(Token thisKeyword) { | 1268 void endFormalParameter(Token thisKeyword) { |
| 1265 debugEvent("FormalParameter"); | 1269 debugEvent("FormalParameter"); |
| 1270 // TODO(ahe): Need beginToken here. | |
| 1271 int charOffset = thisKeyword?.charOffset; | |
| 1266 if (thisKeyword != null) { | 1272 if (thisKeyword != null) { |
| 1267 if (!inConstructor) { | 1273 if (!inConstructor) { |
| 1268 return inputError("'this' parameters can only be used on constructors.", | 1274 return inputError("'this' parameters can only be used on constructors.", |
| 1269 thisKeyword.charOffset); | 1275 thisKeyword.charOffset); |
| 1270 } | 1276 } |
| 1271 } | 1277 } |
| 1272 Identifier name = pop(); | 1278 Identifier name = pop(); |
| 1273 DartType type = pop(); | 1279 DartType type = pop(); |
| 1274 pop(); // Modifiers. | 1280 pop(); // Modifiers. |
| 1275 ignore(Unhandled.Metadata); | 1281 ignore(Unhandled.Metadata); |
| 1276 VariableDeclaration variable; | 1282 VariableDeclaration variable; |
| 1277 if (!inCatchClause && functionNestingLevel == 0) { | 1283 if (!inCatchClause && functionNestingLevel == 0) { |
| 1278 var builder = formalParameterScope.lookup(name.name); | 1284 var builder = formalParameterScope.lookup(name.name, charOffset, uri); |
| 1279 if (builder == null) { | 1285 if (builder == null) { |
| 1280 return inputError("'${name.name}' isn't a field in this class.", | 1286 return inputError("'${name.name}' isn't a field in this class.", |
| 1281 name.fileOffset); | 1287 name.fileOffset); |
| 1282 } | 1288 } |
| 1283 if (thisKeyword == null) { | 1289 if (thisKeyword == null) { |
| 1284 variable = builder.build(); | 1290 variable = builder.build(); |
| 1285 variable.initializer = name.initializer; | 1291 variable.initializer = name.initializer; |
| 1286 } else if (builder.isField && builder.parent == classBuilder) { | 1292 } else if (builder.isField && builder.parent == classBuilder) { |
| 1287 FieldBuilder field = builder; | 1293 FieldBuilder field = builder; |
| 1288 if (type != null) { | 1294 if (type != null) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1346 debugEvent("FormalParameters"); | 1352 debugEvent("FormalParameters"); |
| 1347 OptionalFormals optional; | 1353 OptionalFormals optional; |
| 1348 if (count > 0 && peek() is OptionalFormals) { | 1354 if (count > 0 && peek() is OptionalFormals) { |
| 1349 optional = pop(); | 1355 optional = pop(); |
| 1350 count--; | 1356 count--; |
| 1351 } | 1357 } |
| 1352 FormalParameters formals = new FormalParameters( | 1358 FormalParameters formals = new FormalParameters( |
| 1353 popList(count) ?? <VariableDeclaration>[], optional); | 1359 popList(count) ?? <VariableDeclaration>[], optional); |
| 1354 push(formals); | 1360 push(formals); |
| 1355 if (inCatchClause || functionNestingLevel != 0) { | 1361 if (inCatchClause || functionNestingLevel != 0) { |
| 1356 enterLocalScope(formals.computeFormalParameterScope(scope)); | 1362 enterLocalScope(formals.computeFormalParameterScope( |
| 1363 scope, member ?? classBuilder ?? library)); | |
| 1357 } | 1364 } |
| 1358 } | 1365 } |
| 1359 | 1366 |
| 1360 @override | 1367 @override |
| 1361 void beginCatchClause(Token token) { | 1368 void beginCatchClause(Token token) { |
| 1362 debugEvent("beginCatchClause"); | 1369 debugEvent("beginCatchClause"); |
| 1363 inCatchClause = true; | 1370 inCatchClause = true; |
| 1364 } | 1371 } |
| 1365 | 1372 |
| 1366 @override | 1373 @override |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1711 } | 1718 } |
| 1712 | 1719 |
| 1713 @override | 1720 @override |
| 1714 void endFunctionName(Token token) { | 1721 void endFunctionName(Token token) { |
| 1715 debugEvent("FunctionName"); | 1722 debugEvent("FunctionName"); |
| 1716 Identifier name = pop(); | 1723 Identifier name = pop(); |
| 1717 VariableDeclaration variable = new VariableDeclaration( | 1724 VariableDeclaration variable = new VariableDeclaration( |
| 1718 name.name, isFinal: true); | 1725 name.name, isFinal: true); |
| 1719 push(new FunctionDeclaration(variable, | 1726 push(new FunctionDeclaration(variable, |
| 1720 new FunctionNode(new InvalidStatement()))); | 1727 new FunctionNode(new InvalidStatement()))); |
| 1721 scope[variable.name] = new KernelVariableBuilder(variable); | 1728 scope[variable.name] = |
| 1729 new KernelVariableBuilder(variable, member ?? classBuilder); | |
|
Johnni Winther
2017/02/13 08:42:03
Ditto.
ahe
2017/02/13 10:44:23
Done.
| |
| 1722 enterLocalScope(); | 1730 enterLocalScope(); |
| 1723 } | 1731 } |
| 1724 | 1732 |
| 1725 @override | 1733 @override |
| 1726 void beginFunction(Token token) { | 1734 void beginFunction(Token token) { |
| 1727 debugEvent("beginFunction"); | 1735 debugEvent("beginFunction"); |
| 1728 functionNestingLevel++; | 1736 functionNestingLevel++; |
| 1729 } | 1737 } |
| 1730 | 1738 |
| 1731 @override | 1739 @override |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1861 debugEvent("Label"); | 1869 debugEvent("Label"); |
| 1862 Identifier identifier = pop(); | 1870 Identifier identifier = pop(); |
| 1863 push(new Label(identifier.name)); | 1871 push(new Label(identifier.name)); |
| 1864 } | 1872 } |
| 1865 | 1873 |
| 1866 @override | 1874 @override |
| 1867 void beginLabeledStatement(Token token, int labelCount) { | 1875 void beginLabeledStatement(Token token, int labelCount) { |
| 1868 debugEvent("beginLabeledStatement"); | 1876 debugEvent("beginLabeledStatement"); |
| 1869 List<Label> labels = popList(labelCount); | 1877 List<Label> labels = popList(labelCount); |
| 1870 enterLocalScope(); | 1878 enterLocalScope(); |
| 1871 LabelTarget target = new LabelTarget(); | 1879 LabelTarget target = new LabelTarget(member, token.charOffset); |
| 1872 for (Label label in labels) { | 1880 for (Label label in labels) { |
| 1873 scope[label.name] = target; | 1881 scope[label.name] = target; |
| 1874 } | 1882 } |
| 1875 push(target); | 1883 push(target); |
| 1876 } | 1884 } |
| 1877 | 1885 |
| 1878 @override | 1886 @override |
| 1879 void endLabeledStatement(int labelCount) { | 1887 void endLabeledStatement(int labelCount) { |
| 1880 debugEvent("LabeledStatement"); | 1888 debugEvent("LabeledStatement"); |
| 1881 Statement statement = popStatement(); | 1889 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) { | 1954 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { |
| 1947 debugEvent("YieldStatement"); | 1955 debugEvent("YieldStatement"); |
| 1948 push(new YieldStatement(popForValue(), isYieldStar: starToken != null)); | 1956 push(new YieldStatement(popForValue(), isYieldStar: starToken != null)); |
| 1949 } | 1957 } |
| 1950 | 1958 |
| 1951 @override | 1959 @override |
| 1952 void beginSwitchBlock(Token token) { | 1960 void beginSwitchBlock(Token token) { |
| 1953 debugEvent("beginSwitchBlock"); | 1961 debugEvent("beginSwitchBlock"); |
| 1954 enterLocalScope(); | 1962 enterLocalScope(); |
| 1955 enterSwitchScope(); | 1963 enterSwitchScope(); |
| 1956 enterBreakTarget(); | 1964 enterBreakTarget(token.charOffset); |
| 1957 } | 1965 } |
| 1958 | 1966 |
| 1959 @override | 1967 @override |
| 1960 void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) { | 1968 void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) { |
| 1961 debugEvent("beginSwitchCase"); | 1969 debugEvent("beginSwitchCase"); |
| 1962 List labelsAndExpressions = popList(labelCount + expressionCount); | 1970 List labelsAndExpressions = popList(labelCount + expressionCount); |
| 1963 List<Label> labels = <Label>[]; | 1971 List<Label> labels = <Label>[]; |
| 1964 List<Expression> expressions = <Expression>[]; | 1972 List<Expression> expressions = <Expression>[]; |
| 1965 if (labelsAndExpressions != null) { | 1973 if (labelsAndExpressions != null) { |
| 1966 for (var labelOrExpression in labelsAndExpressions) { | 1974 for (var labelOrExpression in labelsAndExpressions) { |
| 1967 if (labelOrExpression is Label) { | 1975 if (labelOrExpression is Label) { |
| 1968 labels.add(labelOrExpression); | 1976 labels.add(labelOrExpression); |
| 1969 } else { | 1977 } else { |
| 1970 expressions.add(toValue(labelOrExpression)); | 1978 expressions.add(toValue(labelOrExpression)); |
| 1971 } | 1979 } |
| 1972 } | 1980 } |
| 1973 } | 1981 } |
| 1974 assert(scope == switchScope); | 1982 assert(scope == switchScope); |
| 1975 for (Label label in labels) { | 1983 for (Label label in labels) { |
| 1976 Builder existing = scope.local[label.name]; | 1984 Builder existing = scope.local[label.name]; |
| 1977 if (existing == null) { | 1985 if (existing == null) { |
| 1978 scope[label.name] = createGotoTarget(); | 1986 scope[label.name] = createGotoTarget(firstToken.charOffset); |
| 1979 } else { | 1987 } else { |
| 1980 // TODO(ahe): Should validate this is a goto target and not duplicated. | 1988 // TODO(ahe): Should validate this is a goto target and not duplicated. |
| 1981 } | 1989 } |
| 1982 } | 1990 } |
| 1983 push(expressions); | 1991 push(expressions); |
| 1984 push(labels); | 1992 push(labels); |
| 1985 enterLocalScope(); | 1993 enterLocalScope(); |
| 1986 } | 1994 } |
| 1987 | 1995 |
| 1988 @override | 1996 @override |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2010 | 2018 |
| 2011 @override | 2019 @override |
| 2012 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | 2020 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { |
| 2013 debugEvent("SwitchBlock"); | 2021 debugEvent("SwitchBlock"); |
| 2014 List<SwitchCase> cases = | 2022 List<SwitchCase> cases = |
| 2015 new List<SwitchCase>.filled(caseCount, null, growable: true); | 2023 new List<SwitchCase>.filled(caseCount, null, growable: true); |
| 2016 for (int i = caseCount - 1; i >= 0; i--) { | 2024 for (int i = caseCount - 1; i >= 0; i--) { |
| 2017 List<Label> labels = pop(); | 2025 List<Label> labels = pop(); |
| 2018 SwitchCase current = cases[i] = pop(); | 2026 SwitchCase current = cases[i] = pop(); |
| 2019 for (Label label in labels) { | 2027 for (Label label in labels) { |
| 2020 JumpTarget target = switchScope.lookup(label.name); | 2028 JumpTarget target = |
| 2029 switchScope.lookup(label.name, label.fileOffset, uri); | |
| 2021 if (target != null) { | 2030 if (target != null) { |
| 2022 target.resolveGotos(current); | 2031 target.resolveGotos(current); |
| 2023 } | 2032 } |
| 2024 } | 2033 } |
| 2025 // TODO(ahe): Validate that there's only one default and it's last. | 2034 // TODO(ahe): Validate that there's only one default and it's last. |
| 2026 } | 2035 } |
| 2027 JumpTarget target = exitBreakTarget(); | 2036 JumpTarget target = exitBreakTarget(); |
| 2028 exitSwitchScope(); | 2037 exitSwitchScope(); |
| 2029 exitLocalScope(); | 2038 exitLocalScope(); |
| 2030 Expression expression = popForValue(); | 2039 Expression expression = popForValue(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2044 | 2053 |
| 2045 @override | 2054 @override |
| 2046 void handleBreakStatement( | 2055 void handleBreakStatement( |
| 2047 bool hasTarget, Token breakKeyword, Token endToken) { | 2056 bool hasTarget, Token breakKeyword, Token endToken) { |
| 2048 debugEvent("BreakStatement"); | 2057 debugEvent("BreakStatement"); |
| 2049 var target = breakTarget; | 2058 var target = breakTarget; |
| 2050 String name; | 2059 String name; |
| 2051 if (hasTarget) { | 2060 if (hasTarget) { |
| 2052 Identifier identifier = pop(); | 2061 Identifier identifier = pop(); |
| 2053 name = identifier.name; | 2062 name = identifier.name; |
| 2054 target = scope.lookup(identifier.name); | 2063 target = scope.lookup( |
| 2064 identifier.name, breakKeyword.next.charOffset, uri); | |
| 2055 } | 2065 } |
| 2056 if (target == null && name == null) { | 2066 if (target == null && name == null) { |
| 2057 push(compileTimeErrorInLoopOrSwitch = | 2067 push(compileTimeErrorInLoopOrSwitch = |
| 2058 buildCompileTimeErrorStatement( | 2068 buildCompileTimeErrorStatement( |
| 2059 "No target of break.", breakKeyword.charOffset)); | 2069 "No target of break.", breakKeyword.charOffset)); |
| 2060 } else if (target == null || target is! JumpTarget | 2070 } else if (target == null || target is! JumpTarget |
| 2061 || !target.isBreakTarget) { | 2071 || !target.isBreakTarget) { |
| 2062 push(compileTimeErrorInLoopOrSwitch = | 2072 push(compileTimeErrorInLoopOrSwitch = |
| 2063 buildCompileTimeErrorStatement("Can't break to '$name'.", | 2073 buildCompileTimeErrorStatement("Can't break to '$name'.", |
| 2064 breakKeyword.next.charOffset)); | 2074 breakKeyword.next.charOffset)); |
| 2065 } else { | 2075 } else { |
| 2066 BreakStatement statement = new BreakStatement(null); | 2076 BreakStatement statement = new BreakStatement(null); |
| 2067 target.addBreak(statement); | 2077 target.addBreak(statement); |
| 2068 push(statement); | 2078 push(statement); |
| 2069 } | 2079 } |
| 2070 } | 2080 } |
| 2071 | 2081 |
| 2072 @override | 2082 @override |
| 2073 void handleContinueStatement( | 2083 void handleContinueStatement( |
| 2074 bool hasTarget, Token continueKeyword, Token endToken) { | 2084 bool hasTarget, Token continueKeyword, Token endToken) { |
| 2075 debugEvent("ContinueStatement"); | 2085 debugEvent("ContinueStatement"); |
| 2076 var target = continueTarget; | 2086 var target = continueTarget; |
| 2077 String name; | 2087 String name; |
| 2078 if (hasTarget) { | 2088 if (hasTarget) { |
| 2079 Identifier identifier = pop(); | 2089 Identifier identifier = pop(); |
| 2080 name = identifier.name; | 2090 name = identifier.name; |
| 2081 target = scope.lookup(identifier.name); | 2091 target = scope.lookup( |
| 2092 identifier.name, continueKeyword.next.charOffset, uri); | |
| 2082 if (target != null && target is! JumpTarget) { | 2093 if (target != null && target is! JumpTarget) { |
| 2083 push(compileTimeErrorInLoopOrSwitch = | 2094 push(compileTimeErrorInLoopOrSwitch = |
| 2084 buildCompileTimeErrorStatement( | 2095 buildCompileTimeErrorStatement( |
| 2085 "Target of continue must be a label.", | 2096 "Target of continue must be a label.", |
| 2086 continueKeyword.charOffset)); | 2097 continueKeyword.charOffset)); |
| 2087 return; | 2098 return; |
| 2088 } | 2099 } |
| 2089 if (target == null) { | 2100 if (target == null) { |
| 2090 if (switchScope == null) { | 2101 if (switchScope == null) { |
| 2091 push(buildCompileTimeErrorStatement("Can't find label '$name'.", | 2102 push(buildCompileTimeErrorStatement("Can't find label '$name'.", |
| 2092 continueKeyword.next.charOffset)); | 2103 continueKeyword.next.charOffset)); |
| 2093 return; | 2104 return; |
| 2094 } | 2105 } |
| 2095 switchScope[identifier.name] = target = createGotoTarget(); | 2106 switchScope[identifier.name] = target = |
| 2107 createGotoTarget(identifier.fileOffset); | |
| 2096 } | 2108 } |
| 2097 if (target.isGotoTarget) { | 2109 if (target.isGotoTarget) { |
| 2098 ContinueSwitchStatement statement = new ContinueSwitchStatement(null); | 2110 ContinueSwitchStatement statement = new ContinueSwitchStatement(null); |
| 2099 target.addGoto(statement); | 2111 target.addGoto(statement); |
| 2100 push(statement); | 2112 push(statement); |
| 2101 return; | 2113 return; |
| 2102 } | 2114 } |
| 2103 } | 2115 } |
| 2104 if (target == null) { | 2116 if (target == null) { |
| 2105 push(compileTimeErrorInLoopOrSwitch = | 2117 push(compileTimeErrorInLoopOrSwitch = |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2478 return accessor.buildPostfixIncrement(binaryOperator, voidContext: true, | 2490 return accessor.buildPostfixIncrement(binaryOperator, voidContext: true, |
| 2479 interfaceTarget: interfaceTarget); | 2491 interfaceTarget: interfaceTarget); |
| 2480 } | 2492 } |
| 2481 } | 2493 } |
| 2482 | 2494 |
| 2483 class JumpTarget extends Builder { | 2495 class JumpTarget extends Builder { |
| 2484 final List<Statement> users = <Statement>[]; | 2496 final List<Statement> users = <Statement>[]; |
| 2485 | 2497 |
| 2486 final JumpTargetKind kind; | 2498 final JumpTargetKind kind; |
| 2487 | 2499 |
| 2488 JumpTarget(this.kind); | 2500 JumpTarget(this.kind, MemberBuilder member, int charOffset) |
| 2501 : super(member, charOffset, member.fileUri); | |
| 2489 | 2502 |
| 2490 bool get isBreakTarget => kind == JumpTargetKind.Break; | 2503 bool get isBreakTarget => kind == JumpTargetKind.Break; |
| 2491 | 2504 |
| 2492 bool get isContinueTarget => kind == JumpTargetKind.Continue; | 2505 bool get isContinueTarget => kind == JumpTargetKind.Continue; |
| 2493 | 2506 |
| 2494 bool get isGotoTarget => kind == JumpTargetKind.Goto; | 2507 bool get isGotoTarget => kind == JumpTargetKind.Goto; |
| 2495 | 2508 |
| 2496 bool get hasUsers => users.isNotEmpty; | 2509 bool get hasUsers => users.isNotEmpty; |
| 2497 | 2510 |
| 2498 void addBreak(BreakStatement statement) { | 2511 void addBreak(BreakStatement statement) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 2529 void resolveGotos(SwitchCase target) { | 2542 void resolveGotos(SwitchCase target) { |
| 2530 assert(isGotoTarget); | 2543 assert(isGotoTarget); |
| 2531 for (ContinueSwitchStatement user in users) { | 2544 for (ContinueSwitchStatement user in users) { |
| 2532 user.target = target; | 2545 user.target = target; |
| 2533 } | 2546 } |
| 2534 users.clear(); | 2547 users.clear(); |
| 2535 } | 2548 } |
| 2536 } | 2549 } |
| 2537 | 2550 |
| 2538 class LabelTarget extends Builder implements JumpTarget { | 2551 class LabelTarget extends Builder implements JumpTarget { |
| 2539 final JumpTarget breakTarget = new JumpTarget(JumpTargetKind.Break); | 2552 final JumpTarget breakTarget; |
| 2540 | 2553 |
| 2541 final JumpTarget continueTarget = new JumpTarget(JumpTargetKind.Continue); | 2554 final JumpTarget continueTarget; |
| 2542 | 2555 |
| 2543 LabelTarget(); | 2556 LabelTarget(MemberBuilder member, int charOffset) |
| 2557 : breakTarget = new JumpTarget(JumpTargetKind.Break, member, charOffset), | |
| 2558 continueTarget = | |
| 2559 new JumpTarget(JumpTargetKind.Continue, member, charOffset), | |
| 2560 super(member, charOffset, member.fileUri); | |
| 2544 | 2561 |
| 2545 bool get hasUsers => breakTarget.hasUsers || continueTarget.hasUsers; | 2562 bool get hasUsers => breakTarget.hasUsers || continueTarget.hasUsers; |
| 2546 | 2563 |
| 2547 List<Statement> get users => internalError("Unsupported operation."); | 2564 List<Statement> get users => internalError("Unsupported operation."); |
| 2548 | 2565 |
| 2549 JumpTargetKind get kind => internalError("Unsupported operation."); | 2566 JumpTargetKind get kind => internalError("Unsupported operation."); |
| 2550 | 2567 |
| 2551 bool get isBreakTarget => true; | 2568 bool get isBreakTarget => true; |
| 2552 | 2569 |
| 2553 bool get isContinueTarget => true; | 2570 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)); | 2644 namedParameters.add(new NamedType(parameter.name, parameter.type)); |
| 2628 } | 2645 } |
| 2629 namedParameters.sort(); | 2646 namedParameters.sort(); |
| 2630 } | 2647 } |
| 2631 } | 2648 } |
| 2632 return new FunctionType(positionalParameters, returnType, | 2649 return new FunctionType(positionalParameters, returnType, |
| 2633 namedParameters: namedParameters, | 2650 namedParameters: namedParameters, |
| 2634 requiredParameterCount: requiredParameterCount); | 2651 requiredParameterCount: requiredParameterCount); |
| 2635 } | 2652 } |
| 2636 | 2653 |
| 2637 Scope computeFormalParameterScope(Scope parent) { | 2654 Scope computeFormalParameterScope(Scope parent, Builder builder) { |
| 2638 if (required.length == 0 && optional == null) return parent; | 2655 if (required.length == 0 && optional == null) return parent; |
| 2639 Map<String, Builder> local = <String, Builder>{}; | 2656 Map<String, Builder> local = <String, Builder>{}; |
| 2640 for (VariableDeclaration parameter in required) { | 2657 for (VariableDeclaration parameter in required) { |
| 2641 local[parameter.name] = new KernelVariableBuilder(parameter); | 2658 local[parameter.name] = new KernelVariableBuilder(parameter, builder); |
| 2642 } | 2659 } |
| 2643 if (optional != null) { | 2660 if (optional != null) { |
| 2644 for (VariableDeclaration parameter in optional.formals) { | 2661 for (VariableDeclaration parameter in optional.formals) { |
| 2645 local[parameter.name] = new KernelVariableBuilder(parameter); | 2662 local[parameter.name] = new KernelVariableBuilder(parameter, builder); |
| 2646 } | 2663 } |
| 2647 } | 2664 } |
| 2648 return new Scope(local, parent, isModifiable: false); | 2665 return new Scope(local, parent, isModifiable: false); |
| 2649 } | 2666 } |
| 2650 } | 2667 } |
| 2651 | 2668 |
| 2652 /// Returns a block like this: | 2669 /// Returns a block like this: |
| 2653 /// | 2670 /// |
| 2654 /// { | 2671 /// { |
| 2655 /// statement; | 2672 /// statement; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2680 } else if (node is TypeDeclarationBuilder) { | 2697 } else if (node is TypeDeclarationBuilder) { |
| 2681 return node.name; | 2698 return node.name; |
| 2682 } else if (node is PrefixBuilder) { | 2699 } else if (node is PrefixBuilder) { |
| 2683 return node.name; | 2700 return node.name; |
| 2684 } else if (node is ThisPropertyAccessor) { | 2701 } else if (node is ThisPropertyAccessor) { |
| 2685 return node.name.name; | 2702 return node.name.name; |
| 2686 } else { | 2703 } else { |
| 2687 return internalError("Unhandled: ${node.runtimeType}"); | 2704 return internalError("Unhandled: ${node.runtimeType}"); |
| 2688 } | 2705 } |
| 2689 } | 2706 } |
| OLD | NEW |