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 '../fasta_codes.dart' | 7 import '../fasta_codes.dart' |
8 show FastaMessage, codeExpectedButGot, codeExpectedFunctionBody; | 8 show FastaMessage, codeExpectedButGot, codeExpectedFunctionBody; |
9 | 9 |
10 import '../parser/parser.dart' | 10 import '../parser/parser.dart' |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
403 Block block = popBlock(count, beginToken); | 403 Block block = popBlock(count, beginToken); |
404 exitLocalScope(); | 404 exitLocalScope(); |
405 push(block); | 405 push(block); |
406 } | 406 } |
407 } | 407 } |
408 | 408 |
409 void prepareInitializers() { | 409 void prepareInitializers() { |
410 ProcedureBuilder member = this.member; | 410 ProcedureBuilder member = this.member; |
411 scope = member.computeFormalParameterInitializerScope(scope); | 411 scope = member.computeFormalParameterInitializerScope(scope); |
412 if (member is KernelConstructorBuilder) { | 412 if (member is KernelConstructorBuilder) { |
413 if (member.isConst && | |
414 (classBuilder.cls.superclass?.isMixinApplication ?? false)) { | |
415 addCompileTimeError(member.charOffset, | |
416 "Can't extend a mixin application and be 'const'."); | |
417 } | |
413 if (member.formals != null) { | 418 if (member.formals != null) { |
414 for (KernelFormalParameterBuilder formal in member.formals) { | 419 for (KernelFormalParameterBuilder formal in member.formals) { |
415 if (formal.hasThis) { | 420 if (formal.hasThis) { |
416 Initializer initializer; | 421 Initializer initializer; |
417 if (member.isExternal) { | 422 if (member.isExternal) { |
418 initializer = buildInvalidInitializer( | 423 initializer = buildInvalidInitializer( |
419 buildCompileTimeError( | 424 buildCompileTimeError( |
420 "An external constructor can't initialize fields.", | 425 "An external constructor can't initialize fields.", |
421 formal.charOffset), | 426 formal.charOffset), |
422 formal.charOffset); | 427 formal.charOffset); |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 @override | 1212 @override |
1208 void endVariableInitializer(Token assignmentOperator) { | 1213 void endVariableInitializer(Token assignmentOperator) { |
1209 debugEvent("VariableInitializer"); | 1214 debugEvent("VariableInitializer"); |
1210 assert(assignmentOperator.stringValue == "="); | 1215 assert(assignmentOperator.stringValue == "="); |
1211 pushNewLocalVariable(popForValue(), equalsToken: assignmentOperator); | 1216 pushNewLocalVariable(popForValue(), equalsToken: assignmentOperator); |
1212 } | 1217 } |
1213 | 1218 |
1214 @override | 1219 @override |
1215 void handleNoVariableInitializer(Token token) { | 1220 void handleNoVariableInitializer(Token token) { |
1216 debugEvent("NoVariableInitializer"); | 1221 debugEvent("NoVariableInitializer"); |
1217 pushNewLocalVariable(null); | 1222 bool isConst = (currentLocalVariableModifiers & constMask) != 0; |
1223 bool isFinal = (currentLocalVariableModifiers & finalMask) != 0; | |
1224 Expression initializer; | |
1225 if (!optional("in", token)) { | |
1226 // A for-in loop-variable can't have an initializer. So let's remain | |
1227 // silent if the next token is `in`. Since a for-in loop can only have | |
1228 // one variable it must be followed by `in`. | |
1229 if (isConst) { | |
1230 initializer = buildCompileTimeError( | |
1231 "A 'const' variable must be initialized.", token.charOffset); | |
1232 } else if (isFinal) { | |
1233 initializer = buildCompileTimeError( | |
1234 "A 'final' variable must be initialized.", token.charOffset); | |
1235 } | |
1236 } | |
1237 pushNewLocalVariable(initializer); | |
1218 } | 1238 } |
1219 | 1239 |
1220 void pushNewLocalVariable(Expression initializer, {Token equalsToken}) { | 1240 void pushNewLocalVariable(Expression initializer, {Token equalsToken}) { |
1221 Identifier identifier = pop(); | 1241 Identifier identifier = pop(); |
1222 assert(currentLocalVariableModifiers != -1); | 1242 assert(currentLocalVariableModifiers != -1); |
1223 bool isConst = (currentLocalVariableModifiers & constMask) != 0; | 1243 bool isConst = (currentLocalVariableModifiers & constMask) != 0; |
1224 bool isFinal = (currentLocalVariableModifiers & finalMask) != 0; | 1244 bool isFinal = (currentLocalVariableModifiers & finalMask) != 0; |
1225 assert(isConst == constantExpressionRequired); | 1245 assert(isConst == constantExpressionRequired); |
1226 push(new KernelVariableDeclaration(identifier.name, functionNestingLevel, | 1246 push(new KernelVariableDeclaration(identifier.name, functionNestingLevel, |
1227 initializer: initializer, | 1247 initializer: initializer, |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1974 List<TypeParameter> typeParameters = target.function.typeParameters; | 1994 List<TypeParameter> typeParameters = target.function.typeParameters; |
1975 if (target is Constructor) { | 1995 if (target is Constructor) { |
1976 assert(!target.enclosingClass.isAbstract); | 1996 assert(!target.enclosingClass.isAbstract); |
1977 typeParameters = target.enclosingClass.typeParameters; | 1997 typeParameters = target.enclosingClass.typeParameters; |
1978 } | 1998 } |
1979 if (!checkArguments(target.function, arguments, typeParameters)) { | 1999 if (!checkArguments(target.function, arguments, typeParameters)) { |
1980 return throwNoSuchMethodError(new NullLiteral()..fileOffset = charOffset, | 2000 return throwNoSuchMethodError(new NullLiteral()..fileOffset = charOffset, |
1981 target.name.name, arguments, charOffset); | 2001 target.name.name, arguments, charOffset); |
1982 } | 2002 } |
1983 if (target is Constructor) { | 2003 if (target is Constructor) { |
2004 if (isConst && !target.isConst) { | |
2005 return buildCompileTimeError("Not a const constructor.", charOffset); | |
2006 } | |
1984 return new KernelConstructorInvocation(target, initialTarget, arguments, | 2007 return new KernelConstructorInvocation(target, initialTarget, arguments, |
1985 isConst: isConst) | 2008 isConst: isConst) |
1986 ..fileOffset = charOffset; | 2009 ..fileOffset = charOffset; |
1987 } else if (target is Procedure && target.kind == ProcedureKind.Factory) { | 2010 } else if (target is Procedure && target.kind == ProcedureKind.Factory) { |
1988 return new KernelFactoryConstructorInvocation( | 2011 return new KernelFactoryConstructorInvocation( |
1989 target, initialTarget, arguments, | 2012 target, initialTarget, arguments, |
1990 isConst: isConst) | 2013 isConst: isConst) |
1991 ..fileOffset = charOffset; | 2014 ..fileOffset = charOffset; |
1992 } else { | 2015 } else { |
2016 Procedure factory = target; | |
Johnni Winther
2017/06/12 07:46:16
Shouldn't this be in the if branch above?
ahe
2017/06/12 08:13:22
Yes, good catch!
This is a merge problem. Paul ad
| |
2017 if (isConst && !factory.isConst) { | |
2018 return buildCompileTimeError("Not a const factory.", charOffset); | |
2019 } | |
1993 return new KernelStaticInvocation(target, arguments, isConst: isConst) | 2020 return new KernelStaticInvocation(target, arguments, isConst: isConst) |
1994 ..fileOffset = charOffset; | 2021 ..fileOffset = charOffset; |
1995 } | 2022 } |
1996 } | 2023 } |
1997 | 2024 |
1998 @override | 2025 @override |
1999 bool checkArguments(FunctionNode function, Arguments arguments, | 2026 bool checkArguments(FunctionNode function, Arguments arguments, |
2000 List<TypeParameter> typeParameters) { | 2027 List<TypeParameter> typeParameters) { |
2001 if (arguments.positional.length < function.requiredParameterCount || | 2028 if (arguments.positional.length < function.requiredParameterCount || |
2002 arguments.positional.length > function.positionalParameters.length) { | 2029 arguments.positional.length > function.positionalParameters.length) { |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2334 JumpTarget breakTarget = exitBreakTarget(); | 2361 JumpTarget breakTarget = exitBreakTarget(); |
2335 if (continueTarget.hasUsers) { | 2362 if (continueTarget.hasUsers) { |
2336 body = new LabeledStatement(body); | 2363 body = new LabeledStatement(body); |
2337 continueTarget.resolveContinues(body); | 2364 continueTarget.resolveContinues(body); |
2338 } | 2365 } |
2339 VariableDeclaration variable; | 2366 VariableDeclaration variable; |
2340 bool declaresVariable = false; | 2367 bool declaresVariable = false; |
2341 if (lvalue is VariableDeclaration) { | 2368 if (lvalue is VariableDeclaration) { |
2342 declaresVariable = true; | 2369 declaresVariable = true; |
2343 variable = lvalue; | 2370 variable = lvalue; |
2371 if (variable.isConst) { | |
2372 addCompileTimeError( | |
2373 variable.fileOffset, "A for-in loop-variable can't be 'const'."); | |
2374 } | |
2344 } else if (lvalue is FastaAccessor) { | 2375 } else if (lvalue is FastaAccessor) { |
2345 /// We are in this case, where `lvalue` isn't a [VariableDeclaration]: | 2376 /// We are in this case, where `lvalue` isn't a [VariableDeclaration]: |
2346 /// | 2377 /// |
2347 /// for (lvalue in expression) body | 2378 /// for (lvalue in expression) body |
2348 /// | 2379 /// |
2349 /// This is normalized to: | 2380 /// This is normalized to: |
2350 /// | 2381 /// |
2351 /// for (final #t in expression) { | 2382 /// for (final #t in expression) { |
2352 /// lvalue = #t; | 2383 /// lvalue = #t; |
2353 /// body; | 2384 /// body; |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2881 buildCompileTimeError( | 2912 buildCompileTimeError( |
2882 "'$name' isn't an instance field of this class.", offset), | 2913 "'$name' isn't an instance field of this class.", offset), |
2883 offset); | 2914 offset); |
2884 } | 2915 } |
2885 } | 2916 } |
2886 | 2917 |
2887 @override | 2918 @override |
2888 Initializer buildSuperInitializer( | 2919 Initializer buildSuperInitializer( |
2889 Constructor constructor, Arguments arguments, | 2920 Constructor constructor, Arguments arguments, |
2890 [int charOffset = -1]) { | 2921 [int charOffset = -1]) { |
2922 if (member.isConst && !constructor.isConst) { | |
2923 return buildInvalidInitializer( | |
2924 buildCompileTimeError("Super constructor isn't const.", charOffset), | |
2925 charOffset); | |
2926 } | |
2891 needsImplicitSuperInitializer = false; | 2927 needsImplicitSuperInitializer = false; |
2892 return new SuperInitializer(constructor, arguments) | 2928 return new SuperInitializer(constructor, arguments) |
2893 ..fileOffset = charOffset; | 2929 ..fileOffset = charOffset; |
2894 } | 2930 } |
2895 | 2931 |
2896 @override | 2932 @override |
2897 Initializer buildRedirectingInitializer( | 2933 Initializer buildRedirectingInitializer( |
2898 Constructor constructor, Arguments arguments, | 2934 Constructor constructor, Arguments arguments, |
2899 [int charOffset = -1]) { | 2935 [int charOffset = -1]) { |
2900 needsImplicitSuperInitializer = false; | 2936 needsImplicitSuperInitializer = false; |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3475 if (starToken == null) { | 3511 if (starToken == null) { |
3476 return AsyncMarker.Async; | 3512 return AsyncMarker.Async; |
3477 } else { | 3513 } else { |
3478 assert(identical(starToken.stringValue, "*")); | 3514 assert(identical(starToken.stringValue, "*")); |
3479 return AsyncMarker.AsyncStar; | 3515 return AsyncMarker.AsyncStar; |
3480 } | 3516 } |
3481 } else { | 3517 } else { |
3482 return internalError("Unknown async modifier: $asyncToken"); | 3518 return internalError("Unknown async modifier: $asyncToken"); |
3483 } | 3519 } |
3484 } | 3520 } |
OLD | NEW |