Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index c90263909dc9b3c5aedec1d54b889f740be59732..bb7921e5e9f3d12792f03ef387197a94f9a3308a 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -52,6 +52,8 @@ DEFINE_FLAG(bool, warn_super, false, |
| "Warning if super initializer not last in initializer list."); |
| DEFINE_FLAG(bool, await_is_keyword, false, |
| "await and yield are treated as proper keywords in synchronous code."); |
| +DEFINE_FLAG(bool, assert_initializer, false, |
| + "Allow asserts in initializer lists."); |
| DECLARE_FLAG(bool, profile_vm); |
| DECLARE_FLAG(bool, trace_service); |
| @@ -2591,6 +2593,9 @@ AstNode* Parser::ParseInitializer(const Class& cls, |
| GrowableArray<Field*>* initialized_fields) { |
| TRACE_PARSER("ParseInitializer"); |
| const TokenPosition field_pos = TokenPos(); |
| + if (FLAG_assert_initializer && CurrentToken() == Token::kASSERT) { |
|
hausner
2016/08/15 20:54:26
Extra parens around the == expression.
|
| + return ParseAssertStatement(current_function().is_const()); |
| + } |
| if (CurrentToken() == Token::kTHIS) { |
| ConsumeToken(); |
| ExpectToken(Token::kPERIOD); |
| @@ -2880,7 +2885,9 @@ void Parser::ParseInitializers(const Class& cls, |
| AstNode* init_statement = |
| ParseInitializer(cls, receiver, initialized_fields); |
| super_init_is_last = false; |
| - current_block_->statements->Add(init_statement); |
| + if (init_statement != NULL) { |
| + current_block_->statements->Add(init_statement); |
| + } |
| } |
| } while (CurrentToken() == Token::kCOMMA); |
| } |
| @@ -3591,6 +3598,10 @@ void Parser::SkipInitializers() { |
| } |
| CheckToken(Token::kLPAREN); |
| SkipToMatchingParenthesis(); |
| + } else if (FLAG_assert_initializer && CurrentToken() == Token::kASSERT) { |
|
hausner
2016/08/15 20:54:26
Extra parens around the == expression.
Lasse Reichstein Nielsen
2016/08/23 07:05:30
Done.
|
| + ConsumeToken(); |
| + CheckToken(Token::kLPAREN); |
| + SkipToMatchingParenthesis(); |
| } else { |
| SkipIf(Token::kTHIS); |
| SkipIf(Token::kPERIOD); |
| @@ -9194,7 +9205,7 @@ AstNode* Parser::MakeStaticCall(const String& cls_name, |
| } |
| -AstNode* Parser::ParseAssertStatement() { |
| +AstNode* Parser::ParseAssertStatement(bool is_const) { |
| TRACE_PARSER("ParseAssertStatement"); |
| ConsumeToken(); // Consume assert keyword. |
| ExpectToken(Token::kLPAREN); |
| @@ -9205,18 +9216,36 @@ AstNode* Parser::ParseAssertStatement() { |
| return NULL; |
| } |
| AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| + if (is_const && !condition->IsPotentiallyConst()) { |
| + ReportError(condition_pos, |
| + "initializer assert expression must be compile time constant."); |
| + } |
| const TokenPosition condition_end = TokenPos(); |
| ExpectToken(Token::kRPAREN); |
| + // Reuse the _AssertionError._checkAssertion function for const calls as well, |
| + // but ensure that the value is a bool. |
|
Lasse Reichstein Nielsen
2016/07/07 12:48:41
Another option is to have a separate function that
hausner
2016/08/15 20:54:26
Maybe option 2 is cleaner. I'd prefer a separate f
Lasse Reichstein Nielsen
2016/08/23 07:05:31
Will do.
|
| ArgumentListNode* arguments = new(Z) ArgumentListNode(condition_pos); |
| - arguments->Add(condition); |
| + if (is_const) { |
| + arguments->Add(new(Z) LiteralNode(condition_pos, Bool::False())); |
|
hausner
2016/08/15 20:54:26
I don't see a bool parameter in _AssertionError._c
Lasse Reichstein Nielsen
2016/08/23 07:05:31
Since I already checked the condition in the `IfNo
|
| + } else { |
| + arguments->Add(condition); |
| + } |
| arguments->Add(new(Z) LiteralNode(condition_pos, |
| Integer::ZoneHandle(Z, Integer::New(condition_pos.value(), Heap::kOld)))); |
| arguments->Add(new(Z) LiteralNode(condition_end, |
| Integer::ZoneHandle(Z, Integer::New(condition_end.value(), Heap::kOld)))); |
| - return MakeStaticCall(Symbols::AssertionError(), |
| - Library::PrivateCoreLibName(Symbols::CheckAssertion()), |
| - arguments); |
| + AstNode* assert_throw = MakeStaticCall(Symbols::AssertionError(), |
| + Library::PrivateCoreLibName(Symbols::CheckAssertion()), |
| + arguments); |
| + |
| + if (!is_const) return assert_throw; |
| + condition = new(Z) UnaryOpNode(condition_pos, Token::kNOT, condition); |
| + return new(Z) IfNode( |
| + condition_pos, |
| + condition, |
|
hausner
2016/08/15 20:54:26
I don't think you can use the 'condition' expressi
Lasse Reichstein Nielsen
2016/08/23 07:05:31
I don't, as explained above.
|
| + NodeAsSequenceNode(condition_pos, assert_throw, NULL), |
| + NULL); |
| } |