Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index e9e6e93b215b35c03ca941902529e795dc244fa2..9cab33698be6b944b0b4f5efa0f1d8ddea440009 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -55,6 +55,8 @@ DEFINE_FLAG(bool, warn_super, false, |
DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax."); |
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); |
@@ -2668,6 +2670,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) { |
+ return ParseAssertStatement(current_function().is_const()); |
+ } |
if (CurrentToken() == Token::kTHIS) { |
ConsumeToken(); |
ExpectToken(Token::kPERIOD); |
@@ -2957,7 +2962,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); |
} |
@@ -3659,6 +3666,10 @@ void Parser::SkipInitializers() { |
} |
CheckToken(Token::kLPAREN); |
SkipToMatchingParenthesis(); |
+ } else if (FLAG_assert_initializer && (CurrentToken() == Token::kASSERT)) { |
+ ConsumeToken(); |
+ CheckToken(Token::kLPAREN); |
+ SkipToMatchingParenthesis(); |
} else { |
SkipIf(Token::kTHIS); |
SkipIf(Token::kPERIOD); |
@@ -9288,7 +9299,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); |
@@ -9299,6 +9310,10 @@ 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); |
@@ -9308,9 +9323,12 @@ AstNode* Parser::ParseAssertStatement() { |
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(is_const ? Symbols::CheckConstAssertion() |
+ : Symbols::CheckAssertion()), |
+ arguments); |
+ |
+ return assert_throw; |
} |