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

Unified Diff: runtime/vm/parser.cc

Issue 2002923002: Implement assert in initializer list in VM. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Update to match updated design document. Created 4 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/assert_initializer_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/assert_initializer_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698