| 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 20 matching lines...) Expand all Loading... |
| 31 import 'package:front_end/src/fasta/scanner/token.dart' show | 31 import 'package:front_end/src/fasta/scanner/token.dart' show |
| 32 BeginGroupToken, | 32 BeginGroupToken, |
| 33 Token, | 33 Token, |
| 34 isBinaryOperator, | 34 isBinaryOperator, |
| 35 isMinusOperator; | 35 isMinusOperator; |
| 36 | 36 |
| 37 import '../errors.dart' show | 37 import '../errors.dart' show |
| 38 InputError, | 38 InputError, |
| 39 internalError; | 39 internalError; |
| 40 | 40 |
| 41 import '../errors.dart' as errors show | |
| 42 inputError; | |
| 43 | |
| 44 import '../source/scope_listener.dart' show | 41 import '../source/scope_listener.dart' show |
| 45 JumpTargetKind, | 42 JumpTargetKind, |
| 46 NullValue, | 43 NullValue, |
| 47 ScopeListener; | 44 ScopeListener; |
| 48 | 45 |
| 49 import '../builder/scope.dart' show | 46 import '../builder/scope.dart' show |
| 50 AccessErrorBuilder, | 47 AccessErrorBuilder, |
| 51 AmbiguousBuilder, | 48 AmbiguousBuilder, |
| 52 Scope; | 49 Scope; |
| 53 | 50 |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 } else { | 409 } else { |
| 413 if (node is !Throw) { | 410 if (node is !Throw) { |
| 414 node = wrapInvalid(node); | 411 node = wrapInvalid(node); |
| 415 } | 412 } |
| 416 initializer = | 413 initializer = |
| 417 new LocalInitializer(new VariableDeclaration.forValue(node)); | 414 new LocalInitializer(new VariableDeclaration.forValue(node)); |
| 418 } | 415 } |
| 419 if (member is KernelConstructorBuilder) { | 416 if (member is KernelConstructorBuilder) { |
| 420 member.addInitializer(initializer); | 417 member.addInitializer(initializer); |
| 421 } else { | 418 } else { |
| 422 inputError("Can't have initializers: ${member.name}", token.charOffset); | 419 addCompileTimeError(token.charOffset, |
| 420 "Can't have initializers: ${member.name}"); |
| 423 } | 421 } |
| 424 } | 422 } |
| 425 | 423 |
| 426 @override | 424 @override |
| 427 void handleNoInitializers() { | 425 void handleNoInitializers() { |
| 428 debugEvent("NoInitializers"); | 426 debugEvent("NoInitializers"); |
| 429 } | 427 } |
| 430 | 428 |
| 431 @override | 429 @override |
| 432 void endInitializers(int count, Token beginToken, Token endToken) { | 430 void endInitializers(int count, Token beginToken, Token endToken) { |
| 433 debugEvent("Initializers"); | 431 debugEvent("Initializers"); |
| 434 } | 432 } |
| 435 | 433 |
| 436 @override | 434 @override |
| 437 void finishFunction(FormalParameters formals, | 435 void finishFunction(FormalParameters formals, |
| 438 AsyncMarker asyncModifier, Statement body) { | 436 AsyncMarker asyncModifier, Statement body) { |
| 439 debugEvent("finishFunction"); | 437 debugEvent("finishFunction"); |
| 440 KernelFunctionBuilder builder = member; | 438 KernelFunctionBuilder builder = member; |
| 441 if (builder is KernelConstructorBuilder) { | 439 if (builder is KernelConstructorBuilder) { |
| 442 if (asyncModifier != AsyncMarker.Sync) { | 440 if (asyncModifier != AsyncMarker.Sync) { |
| 443 // TODO(ahe): Change this to a null check. | 441 // TODO(ahe): Change this to a null check. |
| 444 inputError("Can't be marked as ${asyncModifier}: ${builder.name}", | 442 addCompileTimeError(body?.fileOffset, |
| 445 body?.fileOffset); | 443 "Can't be marked as ${asyncModifier}: ${builder.name}"); |
| 446 } | 444 } |
| 447 } else if (builder is KernelProcedureBuilder) { | 445 } else if (builder is KernelProcedureBuilder) { |
| 448 builder.asyncModifier = asyncModifier; | 446 builder.asyncModifier = asyncModifier; |
| 449 } else { | 447 } else { |
| 450 internalError("Unhandled: ${builder.runtimeType}"); | 448 internalError("Unhandled: ${builder.runtimeType}"); |
| 451 } | 449 } |
| 452 builder.body = body; | 450 builder.body = body; |
| 453 if (formals?.optional != null) { | 451 if (formals?.optional != null) { |
| 454 Iterator<FormalParameterBuilder> formalBuilders = | 452 Iterator<FormalParameterBuilder> formalBuilders = |
| 455 builder.formals.skip(formals.required.length).iterator; | 453 builder.formals.skip(formals.required.length).iterator; |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 } | 1159 } |
| 1162 | 1160 |
| 1163 @override | 1161 @override |
| 1164 void endType(Token beginToken, Token endToken) { | 1162 void endType(Token beginToken, Token endToken) { |
| 1165 // TODO(ahe): The scope is wrong for return types of generic functions. | 1163 // TODO(ahe): The scope is wrong for return types of generic functions. |
| 1166 debugEvent("Type"); | 1164 debugEvent("Type"); |
| 1167 List<DartType> arguments = pop(); | 1165 List<DartType> arguments = pop(); |
| 1168 var name = pop(); | 1166 var name = pop(); |
| 1169 if (name is List) { | 1167 if (name is List) { |
| 1170 if (name.length != 2) { | 1168 if (name.length != 2) { |
| 1171 return internalError("Unexpected: $name.length"); | 1169 internalError("Unexpected: $name.length"); |
| 1172 } | 1170 } |
| 1173 var prefix = name[0]; | 1171 var prefix = name[0]; |
| 1174 if (prefix is Identifier) { | 1172 if (prefix is Identifier) { |
| 1175 prefix = prefix.name; | 1173 prefix = prefix.name; |
| 1176 } | 1174 } |
| 1177 var suffix = name[1]; | 1175 var suffix = name[1]; |
| 1178 if (suffix is Identifier) { | 1176 if (suffix is Identifier) { |
| 1179 suffix = suffix.name; | 1177 suffix = suffix.name; |
| 1180 } | 1178 } |
| 1181 Builder builder; | 1179 Builder builder; |
| 1182 if (prefix is Builder) { | 1180 if (prefix is Builder) { |
| 1183 builder = prefix; | 1181 builder = prefix; |
| 1184 } else { | 1182 } else { |
| 1185 builder = scope.lookup(prefix, beginToken.charOffset, uri); | 1183 builder = scope.lookup(prefix, beginToken.charOffset, uri); |
| 1186 } | 1184 } |
| 1187 if (builder is PrefixBuilder) { | 1185 if (builder is PrefixBuilder) { |
| 1188 name = builder.exports[suffix]; | 1186 name = builder.exports[suffix]; |
| 1189 } else { | 1187 } else { |
| 1190 return inputError( | 1188 push(const DynamicType()); |
| 1191 "Can't be used as a type: '${debugName(prefix, suffix)}'.", | 1189 addCompileTimeError(beginToken.charOffset, |
| 1192 beginToken.charOffset); | 1190 "Can't be used as a type: '${debugName(prefix, suffix)}'."); |
| 1191 return; |
| 1193 } | 1192 } |
| 1194 } | 1193 } |
| 1195 if (name is Identifier) { | 1194 if (name is Identifier) { |
| 1196 name = name.name; | 1195 name = name.name; |
| 1197 } | 1196 } |
| 1198 if (name is BuilderAccessor) { | 1197 if (name is BuilderAccessor) { |
| 1199 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset); | 1198 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset); |
| 1200 push(const DynamicType()); | 1199 push(const DynamicType()); |
| 1201 } else if (name is UnresolvedIdentifier) { | 1200 } else if (name is UnresolvedIdentifier) { |
| 1202 warning("'${name.name}' isn't a type.", beginToken.charOffset); | 1201 warning("'${name.name}' isn't a type.", beginToken.charOffset); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 push(new Throw(expression)); | 1263 push(new Throw(expression)); |
| 1265 } | 1264 } |
| 1266 | 1265 |
| 1267 @override | 1266 @override |
| 1268 void endFormalParameter(Token thisKeyword) { | 1267 void endFormalParameter(Token thisKeyword) { |
| 1269 debugEvent("FormalParameter"); | 1268 debugEvent("FormalParameter"); |
| 1270 // TODO(ahe): Need beginToken here. | 1269 // TODO(ahe): Need beginToken here. |
| 1271 int charOffset = thisKeyword?.charOffset; | 1270 int charOffset = thisKeyword?.charOffset; |
| 1272 if (thisKeyword != null) { | 1271 if (thisKeyword != null) { |
| 1273 if (!inConstructor) { | 1272 if (!inConstructor) { |
| 1274 return inputError("'this' parameters can only be used on constructors.", | 1273 addCompileTimeError(thisKeyword.charOffset, |
| 1275 thisKeyword.charOffset); | 1274 "'this' parameters can only be used on constructors."); |
| 1275 thisKeyword = null; |
| 1276 } | 1276 } |
| 1277 } | 1277 } |
| 1278 Identifier name = pop(); | 1278 Identifier name = pop(); |
| 1279 DartType type = pop(); | 1279 DartType type = pop(); |
| 1280 pop(); // Modifiers. | 1280 pop(); // Modifiers. |
| 1281 ignore(Unhandled.Metadata); | 1281 ignore(Unhandled.Metadata); |
| 1282 VariableDeclaration variable; | 1282 VariableDeclaration variable; |
| 1283 if (!inCatchClause && functionNestingLevel == 0) { | 1283 if (!inCatchClause && functionNestingLevel == 0) { |
| 1284 var builder = formalParameterScope.lookup(name.name, charOffset, uri); | 1284 var builder = formalParameterScope.lookup(name.name, charOffset, uri); |
| 1285 if (builder == null) { | 1285 if (builder == null) { |
| 1286 return inputError("'${name.name}' isn't a field in this class.", | 1286 if (thisKeyword == null) { |
| 1287 name.fileOffset); | 1287 internalError("Internal error: formal missing for '${name.name}'"); |
| 1288 } | 1288 } else { |
| 1289 if (thisKeyword == null) { | 1289 addCompileTimeError(thisKeyword.charOffset, |
| 1290 "'${name.name}' isn't a field in this class."); |
| 1291 thisKeyword = null; |
| 1292 } |
| 1293 } else if (thisKeyword == null) { |
| 1290 variable = builder.build(); | 1294 variable = builder.build(); |
| 1291 variable.initializer = name.initializer; | 1295 variable.initializer = name.initializer; |
| 1292 } else if (builder.isField && builder.parent == classBuilder) { | 1296 } else if (builder.isField && builder.parent == classBuilder) { |
| 1293 FieldBuilder field = builder; | 1297 FieldBuilder field = builder; |
| 1294 if (type != null) { | 1298 if (type != null) { |
| 1295 nit("Ignoring type on 'this' parameter '${name.name}'.", | 1299 nit("Ignoring type on 'this' parameter '${name.name}'.", |
| 1296 name.fileOffset); | 1300 name.fileOffset); |
| 1297 } | 1301 } |
| 1298 type = field.target.type ?? const DynamicType(); | 1302 type = field.target.type ?? const DynamicType(); |
| 1299 variable = new VariableDeclaration(name.name, type: type, | 1303 variable = new VariableDeclaration(name.name, type: type, |
| 1300 initializer: name.initializer); | 1304 initializer: name.initializer); |
| 1301 } else { | 1305 } else { |
| 1302 return inputError("'${name.name}' isn't a field in this class.", | 1306 addCompileTimeError(name.fileOffset, |
| 1303 name.fileOffset); | 1307 "'${name.name}' isn't a field in this class."); |
| 1304 } | 1308 } |
| 1305 } else { | |
| 1306 variable = new VariableDeclaration(name.name, | |
| 1307 type: type ?? const DynamicType(), initializer: name.initializer); | |
| 1308 } | 1309 } |
| 1310 variable ??= new VariableDeclaration(name.name, |
| 1311 type: type ?? const DynamicType(), initializer: name.initializer); |
| 1309 push(variable); | 1312 push(variable); |
| 1310 } | 1313 } |
| 1311 | 1314 |
| 1312 @override | 1315 @override |
| 1313 void endOptionalFormalParameters( | 1316 void endOptionalFormalParameters( |
| 1314 int count, Token beginToken, Token endToken) { | 1317 int count, Token beginToken, Token endToken) { |
| 1315 debugEvent("OptionalFormalParameters"); | 1318 debugEvent("OptionalFormalParameters"); |
| 1316 FormalParameterType kind = optional("{", beginToken) | 1319 FormalParameterType kind = optional("{", beginToken) |
| 1317 ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 1320 ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
| 1318 push(new OptionalFormals(kind, popList(count))); | 1321 push(new OptionalFormals(kind, popList(count))); |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1845 /// lvalue = #t; | 1848 /// lvalue = #t; |
| 1846 /// body; | 1849 /// body; |
| 1847 /// } | 1850 /// } |
| 1848 variable = new VariableDeclaration.forValue(null); | 1851 variable = new VariableDeclaration.forValue(null); |
| 1849 body = combineStatements( | 1852 body = combineStatements( |
| 1850 new ExpressionStatement( | 1853 new ExpressionStatement( |
| 1851 lvalue.buildAssignment( | 1854 lvalue.buildAssignment( |
| 1852 new VariableGet(variable), voidContext: true)), | 1855 new VariableGet(variable), voidContext: true)), |
| 1853 body); | 1856 body); |
| 1854 } else { | 1857 } else { |
| 1855 throw inputError("Expected lvalue, but got ${lvalue}", | 1858 variable = new VariableDeclaration.forValue( |
| 1856 forToken.next.next.charOffset); | 1859 buildCompileTimeError("Expected lvalue, but got ${lvalue}", |
| 1860 forToken.next.next.charOffset)); |
| 1857 } | 1861 } |
| 1858 Statement result = new ForInStatement(variable, expression, body, | 1862 Statement result = new ForInStatement(variable, expression, body, |
| 1859 isAsync: awaitToken != null); | 1863 isAsync: awaitToken != null); |
| 1860 if (breakTarget.hasUsers) { | 1864 if (breakTarget.hasUsers) { |
| 1861 result = new LabeledStatement(result); | 1865 result = new LabeledStatement(result); |
| 1862 breakTarget.resolveBreaks(result); | 1866 breakTarget.resolveBreaks(result); |
| 1863 } | 1867 } |
| 1864 exitLoopOrSwitch(result); | 1868 exitLoopOrSwitch(result); |
| 1865 } | 1869 } |
| 1866 | 1870 |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2229 return internalError("Unhandled: ${builder.runtimeType}"); | 2233 return internalError("Unhandled: ${builder.runtimeType}"); |
| 2230 } | 2234 } |
| 2231 } | 2235 } |
| 2232 | 2236 |
| 2233 @override | 2237 @override |
| 2234 void handleOperator(Token token) { | 2238 void handleOperator(Token token) { |
| 2235 debugEvent("Operator"); | 2239 debugEvent("Operator"); |
| 2236 push(new Operator(token.stringValue)..fileOffset = token.charOffset); | 2240 push(new Operator(token.stringValue)..fileOffset = token.charOffset); |
| 2237 } | 2241 } |
| 2238 | 2242 |
| 2239 dynamic inputError(String message, [int charOffset = -1]) { | 2243 dynamic addCompileTimeError(int charOffset, String message) { |
| 2240 return errors.inputError(uri, charOffset, message); | 2244 return library.addCompileTimeError(charOffset, message, uri); |
| 2241 } | 2245 } |
| 2242 | 2246 |
| 2243 @override | 2247 @override |
| 2244 void handleInvalidFunctionBody(Token token) { | 2248 void handleInvalidFunctionBody(Token token) { |
| 2245 if (!lastErrorWasNativeFunctionBody) { | 2249 if (!lastErrorWasNativeFunctionBody) { |
| 2246 push(new Block(<Statement>[new InvalidStatement()])); | 2250 push(new Block(<Statement>[new InvalidStatement()])); |
| 2247 } | 2251 } |
| 2248 lastErrorWasNativeFunctionBody = false; | 2252 lastErrorWasNativeFunctionBody = false; |
| 2249 } | 2253 } |
| 2250 | 2254 |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2697 } else if (node is TypeDeclarationBuilder) { | 2701 } else if (node is TypeDeclarationBuilder) { |
| 2698 return node.name; | 2702 return node.name; |
| 2699 } else if (node is PrefixBuilder) { | 2703 } else if (node is PrefixBuilder) { |
| 2700 return node.name; | 2704 return node.name; |
| 2701 } else if (node is ThisPropertyAccessor) { | 2705 } else if (node is ThisPropertyAccessor) { |
| 2702 return node.name.name; | 2706 return node.name.name; |
| 2703 } else { | 2707 } else { |
| 2704 return internalError("Unhandled: ${node.runtimeType}"); | 2708 return internalError("Unhandled: ${node.runtimeType}"); |
| 2705 } | 2709 } |
| 2706 } | 2710 } |
| OLD | NEW |