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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/assert_initializer_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 #include "vm/parser.h" 5 #include "vm/parser.h"
6 #include "vm/flags.h" 6 #include "vm/flags.h"
7 7
8 #ifndef DART_PRECOMPILED_RUNTIME 8 #ifndef DART_PRECOMPILED_RUNTIME
9 9
10 #include "lib/invocation_mirror.h" 10 #include "lib/invocation_mirror.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); 45 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
46 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef."); 46 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
47 // TODO(floitsch): remove the conditional-directive flag, once we publicly 47 // TODO(floitsch): remove the conditional-directive flag, once we publicly
48 // committed to the current version. 48 // committed to the current version.
49 DEFINE_FLAG(bool, conditional_directives, true, 49 DEFINE_FLAG(bool, conditional_directives, true,
50 "Enable conditional directives"); 50 "Enable conditional directives");
51 DEFINE_FLAG(bool, warn_super, false, 51 DEFINE_FLAG(bool, warn_super, false,
52 "Warning if super initializer not last in initializer list."); 52 "Warning if super initializer not last in initializer list.");
53 DEFINE_FLAG(bool, await_is_keyword, false, 53 DEFINE_FLAG(bool, await_is_keyword, false,
54 "await and yield are treated as proper keywords in synchronous code."); 54 "await and yield are treated as proper keywords in synchronous code.");
55 DEFINE_FLAG(bool, assert_initializer, false,
56 "Allow asserts in initializer lists.");
55 57
56 DECLARE_FLAG(bool, profile_vm); 58 DECLARE_FLAG(bool, profile_vm);
57 DECLARE_FLAG(bool, trace_service); 59 DECLARE_FLAG(bool, trace_service);
58 60
59 // Quick access to the current thread, isolate and zone. 61 // Quick access to the current thread, isolate and zone.
60 #define T (thread()) 62 #define T (thread())
61 #define I (isolate()) 63 #define I (isolate())
62 #define Z (zone()) 64 #define Z (zone())
63 65
64 // Quick synthetic token position. 66 // Quick synthetic token position.
(...skipping 2519 matching lines...) Expand 10 before | Expand all | Expand 10 after
2584 } 2586 }
2585 return new StaticCallNode(supercall_pos, super_ctor, arguments); 2587 return new StaticCallNode(supercall_pos, super_ctor, arguments);
2586 } 2588 }
2587 2589
2588 2590
2589 AstNode* Parser::ParseInitializer(const Class& cls, 2591 AstNode* Parser::ParseInitializer(const Class& cls,
2590 LocalVariable* receiver, 2592 LocalVariable* receiver,
2591 GrowableArray<Field*>* initialized_fields) { 2593 GrowableArray<Field*>* initialized_fields) {
2592 TRACE_PARSER("ParseInitializer"); 2594 TRACE_PARSER("ParseInitializer");
2593 const TokenPosition field_pos = TokenPos(); 2595 const TokenPosition field_pos = TokenPos();
2596 if (FLAG_assert_initializer && CurrentToken() == Token::kASSERT) {
hausner 2016/08/15 20:54:26 Extra parens around the == expression.
2597 return ParseAssertStatement(current_function().is_const());
2598 }
2594 if (CurrentToken() == Token::kTHIS) { 2599 if (CurrentToken() == Token::kTHIS) {
2595 ConsumeToken(); 2600 ConsumeToken();
2596 ExpectToken(Token::kPERIOD); 2601 ExpectToken(Token::kPERIOD);
2597 } 2602 }
2598 const String& field_name = *ExpectIdentifier("field name expected"); 2603 const String& field_name = *ExpectIdentifier("field name expected");
2599 ExpectToken(Token::kASSIGN); 2604 ExpectToken(Token::kASSIGN);
2600 2605
2601 const bool saved_mode = SetAllowFunctionLiterals(false); 2606 const bool saved_mode = SetAllowFunctionLiterals(false);
2602 // "this" must not be accessible in initializer expressions. 2607 // "this" must not be accessible in initializer expressions.
2603 receiver->set_invisible(true); 2608 receiver->set_invisible(true);
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
2873 ReportError("duplicate call to super constructor"); 2878 ReportError("duplicate call to super constructor");
2874 } 2879 }
2875 super_init_call = ParseSuperInitializer(cls, receiver); 2880 super_init_call = ParseSuperInitializer(cls, receiver);
2876 super_init_index = current_block_->statements->length(); 2881 super_init_index = current_block_->statements->length();
2877 current_block_->statements->Add(super_init_call); 2882 current_block_->statements->Add(super_init_call);
2878 super_init_is_last = true; 2883 super_init_is_last = true;
2879 } else { 2884 } else {
2880 AstNode* init_statement = 2885 AstNode* init_statement =
2881 ParseInitializer(cls, receiver, initialized_fields); 2886 ParseInitializer(cls, receiver, initialized_fields);
2882 super_init_is_last = false; 2887 super_init_is_last = false;
2883 current_block_->statements->Add(init_statement); 2888 if (init_statement != NULL) {
2889 current_block_->statements->Add(init_statement);
2890 }
2884 } 2891 }
2885 } while (CurrentToken() == Token::kCOMMA); 2892 } while (CurrentToken() == Token::kCOMMA);
2886 } 2893 }
2887 if (super_init_call == NULL) { 2894 if (super_init_call == NULL) {
2888 // Generate implicit super() if we haven't seen an explicit super call 2895 // Generate implicit super() if we haven't seen an explicit super call
2889 // or constructor redirection. 2896 // or constructor redirection.
2890 super_init_call = 2897 super_init_call =
2891 GenerateSuperConstructorCall(cls, TokenPos(), receiver, NULL); 2898 GenerateSuperConstructorCall(cls, TokenPos(), receiver, NULL);
2892 if (super_init_call != NULL) { 2899 if (super_init_call != NULL) {
2893 super_init_index = current_block_->statements->length(); 2900 super_init_index = current_block_->statements->length();
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after
3584 do { 3591 do {
3585 ConsumeToken(); // Colon or comma. 3592 ConsumeToken(); // Colon or comma.
3586 if (CurrentToken() == Token::kSUPER) { 3593 if (CurrentToken() == Token::kSUPER) {
3587 ConsumeToken(); 3594 ConsumeToken();
3588 if (CurrentToken() == Token::kPERIOD) { 3595 if (CurrentToken() == Token::kPERIOD) {
3589 ConsumeToken(); 3596 ConsumeToken();
3590 ExpectIdentifier("identifier expected"); 3597 ExpectIdentifier("identifier expected");
3591 } 3598 }
3592 CheckToken(Token::kLPAREN); 3599 CheckToken(Token::kLPAREN);
3593 SkipToMatchingParenthesis(); 3600 SkipToMatchingParenthesis();
3601 } 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.
3602 ConsumeToken();
3603 CheckToken(Token::kLPAREN);
3604 SkipToMatchingParenthesis();
3594 } else { 3605 } else {
3595 SkipIf(Token::kTHIS); 3606 SkipIf(Token::kTHIS);
3596 SkipIf(Token::kPERIOD); 3607 SkipIf(Token::kPERIOD);
3597 ExpectIdentifier("identifier expected"); 3608 ExpectIdentifier("identifier expected");
3598 ExpectToken(Token::kASSIGN); 3609 ExpectToken(Token::kASSIGN);
3599 SetAllowFunctionLiterals(false); 3610 SetAllowFunctionLiterals(false);
3600 SkipExpr(); 3611 SkipExpr();
3601 SetAllowFunctionLiterals(true); 3612 SetAllowFunctionLiterals(true);
3602 } 3613 }
3603 } while (CurrentToken() == Token::kCOMMA); 3614 } while (CurrentToken() == Token::kCOMMA);
(...skipping 5583 matching lines...) Expand 10 before | Expand all | Expand 10 after
9187 const Function& func = Function::ZoneHandle(Z, 9198 const Function& func = Function::ZoneHandle(Z,
9188 Resolver::ResolveStatic(cls, 9199 Resolver::ResolveStatic(cls,
9189 func_name, 9200 func_name,
9190 arguments->length(), 9201 arguments->length(),
9191 arguments->names())); 9202 arguments->names()));
9192 ASSERT(!func.IsNull()); 9203 ASSERT(!func.IsNull());
9193 return new(Z) StaticCallNode(arguments->token_pos(), func, arguments); 9204 return new(Z) StaticCallNode(arguments->token_pos(), func, arguments);
9194 } 9205 }
9195 9206
9196 9207
9197 AstNode* Parser::ParseAssertStatement() { 9208 AstNode* Parser::ParseAssertStatement(bool is_const) {
9198 TRACE_PARSER("ParseAssertStatement"); 9209 TRACE_PARSER("ParseAssertStatement");
9199 ConsumeToken(); // Consume assert keyword. 9210 ConsumeToken(); // Consume assert keyword.
9200 ExpectToken(Token::kLPAREN); 9211 ExpectToken(Token::kLPAREN);
9201 const TokenPosition condition_pos = TokenPos(); 9212 const TokenPosition condition_pos = TokenPos();
9202 if (!I->asserts()) { 9213 if (!I->asserts()) {
9203 SkipExpr(); 9214 SkipExpr();
9204 ExpectToken(Token::kRPAREN); 9215 ExpectToken(Token::kRPAREN);
9205 return NULL; 9216 return NULL;
9206 } 9217 }
9207 AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); 9218 AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
9219 if (is_const && !condition->IsPotentiallyConst()) {
9220 ReportError(condition_pos,
9221 "initializer assert expression must be compile time constant.");
9222 }
9208 const TokenPosition condition_end = TokenPos(); 9223 const TokenPosition condition_end = TokenPos();
9209 ExpectToken(Token::kRPAREN); 9224 ExpectToken(Token::kRPAREN);
9210 9225
9226 // Reuse the _AssertionError._checkAssertion function for const calls as well,
9227 // 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.
9211 ArgumentListNode* arguments = new(Z) ArgumentListNode(condition_pos); 9228 ArgumentListNode* arguments = new(Z) ArgumentListNode(condition_pos);
9212 arguments->Add(condition); 9229 if (is_const) {
9230 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
9231 } else {
9232 arguments->Add(condition);
9233 }
9213 arguments->Add(new(Z) LiteralNode(condition_pos, 9234 arguments->Add(new(Z) LiteralNode(condition_pos,
9214 Integer::ZoneHandle(Z, Integer::New(condition_pos.value(), Heap::kOld)))); 9235 Integer::ZoneHandle(Z, Integer::New(condition_pos.value(), Heap::kOld))));
9215 arguments->Add(new(Z) LiteralNode(condition_end, 9236 arguments->Add(new(Z) LiteralNode(condition_end,
9216 Integer::ZoneHandle(Z, Integer::New(condition_end.value(), Heap::kOld)))); 9237 Integer::ZoneHandle(Z, Integer::New(condition_end.value(), Heap::kOld))));
9217 return MakeStaticCall(Symbols::AssertionError(), 9238 AstNode* assert_throw = MakeStaticCall(Symbols::AssertionError(),
9218 Library::PrivateCoreLibName(Symbols::CheckAssertion()), 9239 Library::PrivateCoreLibName(Symbols::CheckAssertion()),
9219 arguments); 9240 arguments);
9241
9242 if (!is_const) return assert_throw;
9243 condition = new(Z) UnaryOpNode(condition_pos, Token::kNOT, condition);
9244 return new(Z) IfNode(
9245 condition_pos,
9246 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.
9247 NodeAsSequenceNode(condition_pos, assert_throw, NULL),
9248 NULL);
9220 } 9249 }
9221 9250
9222 9251
9223 // Populate local scope of the catch block with the catch parameters. 9252 // Populate local scope of the catch block with the catch parameters.
9224 void Parser::AddCatchParamsToScope(CatchParamDesc* exception_param, 9253 void Parser::AddCatchParamsToScope(CatchParamDesc* exception_param,
9225 CatchParamDesc* stack_trace_param, 9254 CatchParamDesc* stack_trace_param,
9226 LocalScope* scope) { 9255 LocalScope* scope) {
9227 if (exception_param->name != NULL) { 9256 if (exception_param->name != NULL) {
9228 LocalVariable* var = new(Z) LocalVariable( 9257 LocalVariable* var = new(Z) LocalVariable(
9229 exception_param->token_pos, 9258 exception_param->token_pos,
(...skipping 5406 matching lines...) Expand 10 before | Expand all | Expand 10 after
14636 const ArgumentListNode& function_args, 14665 const ArgumentListNode& function_args,
14637 const LocalVariable* temp_for_last_arg, 14666 const LocalVariable* temp_for_last_arg,
14638 bool is_super_invocation) { 14667 bool is_super_invocation) {
14639 UNREACHABLE(); 14668 UNREACHABLE();
14640 return NULL; 14669 return NULL;
14641 } 14670 }
14642 14671
14643 } // namespace dart 14672 } // namespace dart
14644 14673
14645 #endif // DART_PRECOMPILED_RUNTIME 14674 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« 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