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' 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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |