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

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

Issue 2930673002: Implement initializer asserts. (Closed)
Patch Set: Address comments and tweak error recovery. 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
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' show FormalParameterType, MemberKind, optional; 10 import '../parser/parser.dart'
11 show Assert, FormalParameterType, MemberKind, optional;
11 12
12 import '../parser/identifier_context.dart' show IdentifierContext; 13 import '../parser/identifier_context.dart' show IdentifierContext;
13 14
14 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; 15 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
15 16
16 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; 17 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken;
17 18
18 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart' 19 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'
19 show TypeInferrer; 20 show TypeInferrer;
20 21
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 /// 100 ///
100 /// 1. if the current class is Object, 101 /// 1. if the current class is Object,
101 /// 2. if there is an explicit super initializer, 102 /// 2. if there is an explicit super initializer,
102 /// 3. if there is a redirecting (this) initializer, or 103 /// 3. if there is a redirecting (this) initializer, or
103 /// 4. if a compile-time error prevented us from generating code for an 104 /// 4. if a compile-time error prevented us from generating code for an
104 /// initializer. This avoids cascading errors. 105 /// initializer. This avoids cascading errors.
105 bool needsImplicitSuperInitializer; 106 bool needsImplicitSuperInitializer;
106 107
107 Scope formalParameterScope; 108 Scope formalParameterScope;
108 109
110 /// This is set to true when we start parsing an initializer. We use this to
111 /// find the correct scope for initializers like in this example:
112 ///
113 /// class C {
114 /// final x;
115 /// C(x) : x = x;
116 /// }
117 ///
118 /// When parsing this initializer `x = x`, `x` must be resolved in two
119 /// different scopes. The first `x` must be resolved in the class' scope, the
120 /// second in the formal parameter scope.
109 bool inInitializer = false; 121 bool inInitializer = false;
110 122
111 bool inCatchClause = false; 123 bool inCatchClause = false;
112 124
113 bool inCatchBlock = false; 125 bool inCatchBlock = false;
114 126
115 int functionNestingLevel = 0; 127 int functionNestingLevel = 0;
116 128
117 Statement compileTimeErrorInTry; 129 Statement compileTimeErrorInTry;
118 130
(...skipping 2323 matching lines...) Expand 10 before | Expand all | Expand 10 after
2442 exitLoopOrSwitch(result); 2454 exitLoopOrSwitch(result);
2443 } 2455 }
2444 2456
2445 @override 2457 @override
2446 void handleEmptyStatement(Token token) { 2458 void handleEmptyStatement(Token token) {
2447 debugEvent("EmptyStatement"); 2459 debugEvent("EmptyStatement");
2448 push(new EmptyStatement()); 2460 push(new EmptyStatement());
2449 } 2461 }
2450 2462
2451 @override 2463 @override
2452 void handleAssertStatement(Token assertKeyword, Token leftParenthesis, 2464 void beginAssert(Token assertKeyword, Assert kind) {
2453 Token commaToken, Token rightParenthesis, Token semicolonToken) { 2465 debugEvent("beginAssert");
2454 debugEvent("AssertStatement"); 2466 // If in an assert initializer, make sure [inInitializer] is false so we
2455 Expression message = popForValueIfNotNull(commaToken); 2467 // use the formal parameter scope. If this is any other kind of assert,
2456 Expression condition = popForValue(); 2468 // inInitializer should be false anyway.
2457 push(new AssertStatement(condition, message)); 2469 inInitializer = false;
2458 } 2470 }
2459 2471
2460 @override 2472 @override
2473 void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
2474 Token commaToken, Token rightParenthesis, Token semicolonToken) {
2475 debugEvent("Assert");
2476 Expression message = popForValueIfNotNull(commaToken);
2477 Expression condition = popForValue();
2478 AssertStatement statement = new AssertStatement(condition, message);
2479 switch (kind) {
2480 case Assert.Statement:
2481 push(statement);
2482 break;
2483
2484 case Assert.Expression:
2485 push(buildCompileTimeError("`assert` can't be used as an expression."));
2486 break;
2487
2488 case Assert.Initializer:
2489 push(buildAssertInitializer(statement));
2490 break;
2491 }
2492 }
2493
2494 Initializer buildAssertInitializer(AssertStatement statement) {
2495 // Since kernel only has asserts in statment form, we convert it to an
2496 // expression by wrapping it in an anonymous function which we call
2497 // immediately.
2498 //
2499 // Additionally, kernel has no initializer that evaluates an expression,
2500 // but it does have `LocalInitializer` which requires a variable declartion.
2501 //
2502 // So we produce an initializer like this:
2503 //
2504 // var #t0 = (() { statement; }) ()
2505 return new LocalInitializer(new VariableDeclaration.forValue(
2506 buildMethodInvocation(
2507 new FunctionExpression(new FunctionNode(statement)),
2508 callName,
2509 new Arguments.empty(),
2510 statement.fileOffset,
2511 isConstantExpression: true,
2512 isImplicitCall: true)));
2513 }
2514
2515 @override
2461 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) { 2516 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
2462 debugEvent("YieldStatement"); 2517 debugEvent("YieldStatement");
2463 push(new KernelYieldStatement(popForValue(), isYieldStar: starToken != null) 2518 push(new KernelYieldStatement(popForValue(), isYieldStar: starToken != null)
2464 ..fileOffset = yieldToken.charOffset); 2519 ..fileOffset = yieldToken.charOffset);
2465 } 2520 }
2466 2521
2467 @override 2522 @override
2468 void beginSwitchBlock(Token token) { 2523 void beginSwitchBlock(Token token) {
2469 debugEvent("beginSwitchBlock"); 2524 debugEvent("beginSwitchBlock");
2470 enterLocalScope(); 2525 enterLocalScope();
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after
3422 if (starToken == null) { 3477 if (starToken == null) {
3423 return AsyncMarker.Async; 3478 return AsyncMarker.Async;
3424 } else { 3479 } else {
3425 assert(identical(starToken.stringValue, "*")); 3480 assert(identical(starToken.stringValue, "*"));
3426 return AsyncMarker.AsyncStar; 3481 return AsyncMarker.AsyncStar;
3427 } 3482 }
3428 } else { 3483 } else {
3429 return internalError("Unknown async modifier: $asyncToken"); 3484 return internalError("Unknown async modifier: $asyncToken");
3430 } 3485 }
3431 } 3486 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/fasta_codes_generated.dart ('k') | pkg/front_end/lib/src/fasta/parser/class_member_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698