Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |