Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Issue 2932973003: Various semantic checks regarding const and final. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698