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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax."); | 63 DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax."); |
64 DEFINE_FLAG( | 64 DEFINE_FLAG( |
65 bool, | 65 bool, |
66 await_is_keyword, | 66 await_is_keyword, |
67 false, | 67 false, |
68 "await and yield are treated as proper keywords in synchronous code."); | 68 "await and yield are treated as proper keywords in synchronous code."); |
69 DEFINE_FLAG(bool, | 69 DEFINE_FLAG(bool, |
70 assert_initializer, | 70 assert_initializer, |
71 false, | 71 false, |
72 "Allow asserts in initializer lists."); | 72 "Allow asserts in initializer lists."); |
| 73 DEFINE_FLAG(bool, assert_message, false, "Allow message in assert statements"); |
73 | 74 |
74 DECLARE_FLAG(bool, profile_vm); | 75 DECLARE_FLAG(bool, profile_vm); |
75 DECLARE_FLAG(bool, trace_service); | 76 DECLARE_FLAG(bool, trace_service); |
76 DECLARE_FLAG(bool, ignore_patch_signature_mismatch); | 77 DECLARE_FLAG(bool, ignore_patch_signature_mismatch); |
77 | 78 |
78 // Quick access to the current thread, isolate and zone. | 79 // Quick access to the current thread, isolate and zone. |
79 #define T (thread()) | 80 #define T (thread()) |
80 #define I (isolate()) | 81 #define I (isolate()) |
81 #define Z (zone()) | 82 #define Z (zone()) |
82 | 83 |
(...skipping 9074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9157 } | 9158 } |
9158 | 9159 |
9159 | 9160 |
9160 AstNode* Parser::ParseAssertStatement(bool is_const) { | 9161 AstNode* Parser::ParseAssertStatement(bool is_const) { |
9161 TRACE_PARSER("ParseAssertStatement"); | 9162 TRACE_PARSER("ParseAssertStatement"); |
9162 ConsumeToken(); // Consume assert keyword. | 9163 ConsumeToken(); // Consume assert keyword. |
9163 ExpectToken(Token::kLPAREN); | 9164 ExpectToken(Token::kLPAREN); |
9164 const TokenPosition condition_pos = TokenPos(); | 9165 const TokenPosition condition_pos = TokenPos(); |
9165 if (!I->asserts()) { | 9166 if (!I->asserts()) { |
9166 SkipExpr(); | 9167 SkipExpr(); |
| 9168 if (FLAG_assert_message && (CurrentToken() == Token::kCOMMA)) { |
| 9169 ConsumeToken(); |
| 9170 SkipExpr(); |
| 9171 } |
9167 ExpectToken(Token::kRPAREN); | 9172 ExpectToken(Token::kRPAREN); |
9168 return NULL; | 9173 return NULL; |
9169 } | 9174 } |
9170 AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 9175 |
| 9176 BoolScope saved_seen_await(&parsed_function()->have_seen_await_expr_, false); |
| 9177 AstNode* condition = ParseExpr(kAllowConst, kConsumeCascades); |
9171 if (is_const && !condition->IsPotentiallyConst()) { | 9178 if (is_const && !condition->IsPotentiallyConst()) { |
9172 ReportError(condition_pos, | 9179 ReportError(condition_pos, |
9173 "initializer assert expression must be compile time constant."); | 9180 "initializer assert expression must be compile time constant."); |
9174 } | 9181 } |
9175 const TokenPosition condition_end = TokenPos(); | 9182 const TokenPosition condition_end = TokenPos(); |
| 9183 AstNode* message = NULL; |
| 9184 TokenPosition message_pos = TokenPosition::kNoSource; |
| 9185 if (FLAG_assert_message && CurrentToken() == Token::kCOMMA) { |
| 9186 ConsumeToken(); |
| 9187 message_pos = TokenPos(); |
| 9188 message = ParseExpr(kAllowConst, kConsumeCascades); |
| 9189 if (is_const && !message->IsPotentiallyConst()) { |
| 9190 ReportError( |
| 9191 message_pos, |
| 9192 "initializer assert expression must be compile time constant."); |
| 9193 } |
| 9194 } |
9176 ExpectToken(Token::kRPAREN); | 9195 ExpectToken(Token::kRPAREN); |
9177 | 9196 |
| 9197 if (!is_const) { |
| 9198 // Check for assertion condition being a function if not const. |
| 9199 ArgumentListNode* arguments = new (Z) ArgumentListNode(condition_pos); |
| 9200 arguments->Add(condition); |
| 9201 condition = MakeStaticCall( |
| 9202 Symbols::AssertionError(), |
| 9203 Library::PrivateCoreLibName(Symbols::EvaluateAssertion()), arguments); |
| 9204 } |
| 9205 AstNode* not_condition = |
| 9206 new (Z) UnaryOpNode(condition_pos, Token::kNOT, condition); |
| 9207 |
| 9208 // Build call to _AsertionError._throwNew(start, end, message) |
9178 ArgumentListNode* arguments = new (Z) ArgumentListNode(condition_pos); | 9209 ArgumentListNode* arguments = new (Z) ArgumentListNode(condition_pos); |
9179 arguments->Add(condition); | |
9180 arguments->Add(new (Z) LiteralNode( | 9210 arguments->Add(new (Z) LiteralNode( |
9181 condition_pos, | 9211 condition_pos, |
9182 Integer::ZoneHandle(Z, Integer::New(condition_pos.value(), Heap::kOld)))); | 9212 Integer::ZoneHandle(Z, Integer::New(condition_pos.Pos())))); |
9183 arguments->Add(new (Z) LiteralNode( | 9213 arguments->Add(new (Z) LiteralNode( |
9184 condition_end, | 9214 condition_end, |
9185 Integer::ZoneHandle(Z, Integer::New(condition_end.value(), Heap::kOld)))); | 9215 Integer::ZoneHandle(Z, Integer::New(condition_end.Pos())))); |
| 9216 if (message == NULL) { |
| 9217 message = new (Z) LiteralNode(condition_end, Instance::ZoneHandle(Z)); |
| 9218 } |
| 9219 arguments->Add(message); |
9186 AstNode* assert_throw = MakeStaticCall( | 9220 AstNode* assert_throw = MakeStaticCall( |
9187 Symbols::AssertionError(), | 9221 Symbols::AssertionError(), |
9188 Library::PrivateCoreLibName(is_const ? Symbols::CheckConstAssertion() | 9222 Library::PrivateCoreLibName(Symbols::ThrowNew()), arguments); |
9189 : Symbols::CheckAssertion()), | |
9190 arguments); | |
9191 | 9223 |
9192 return assert_throw; | 9224 AstNode* assertion_check = NULL; |
| 9225 if (parsed_function()->have_seen_await()) { |
| 9226 // The await transformation must be done manually because assertions |
| 9227 // are parsed as statements, not expressions. Thus, we need to check |
| 9228 // explicitely whether the arguments contain await operators. (Note that |
| 9229 // we must not parse the arguments with ParseAwaitableExpr(). In the |
| 9230 // corner case of assert(await a, await b), this would create two |
| 9231 // sibling scopes containing the temporary values for a and b. Both |
| 9232 // values would be allocated in the same internal context variable.) |
| 9233 // |
| 9234 // Build !condition ? _AsertionError._throwNew(...) : null; |
| 9235 // We need to use a conditional expression because the await transformer |
| 9236 // cannot transform if statements. |
| 9237 assertion_check = new (Z) ConditionalExprNode( |
| 9238 condition_pos, not_condition, assert_throw, |
| 9239 new (Z) LiteralNode(condition_pos, Object::null_instance())); |
| 9240 OpenBlock(); |
| 9241 AwaitTransformer at(current_block_->statements, async_temp_scope_); |
| 9242 AstNode* transformed_assertion = at.Transform(assertion_check); |
| 9243 SequenceNode* preamble = CloseBlock(); |
| 9244 preamble->Add(transformed_assertion); |
| 9245 assertion_check = preamble; |
| 9246 } else { |
| 9247 // Build if (!condition) _AsertionError._throwNew(...) |
| 9248 assertion_check = new (Z) |
| 9249 IfNode(condition_pos, not_condition, |
| 9250 NodeAsSequenceNode(condition_pos, assert_throw, NULL), NULL); |
| 9251 } |
| 9252 return assertion_check; |
9193 } | 9253 } |
9194 | 9254 |
9195 | 9255 |
9196 // Populate local scope of the catch block with the catch parameters. | 9256 // Populate local scope of the catch block with the catch parameters. |
9197 void Parser::AddCatchParamsToScope(CatchParamDesc* exception_param, | 9257 void Parser::AddCatchParamsToScope(CatchParamDesc* exception_param, |
9198 CatchParamDesc* stack_trace_param, | 9258 CatchParamDesc* stack_trace_param, |
9199 LocalScope* scope) { | 9259 LocalScope* scope) { |
9200 if (exception_param->name != NULL) { | 9260 if (exception_param->name != NULL) { |
9201 LocalVariable* var = new (Z) | 9261 LocalVariable* var = new (Z) |
9202 LocalVariable(exception_param->token_pos, exception_param->token_pos, | 9262 LocalVariable(exception_param->token_pos, exception_param->token_pos, |
(...skipping 5281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14484 const ArgumentListNode& function_args, | 14544 const ArgumentListNode& function_args, |
14485 const LocalVariable* temp_for_last_arg, | 14545 const LocalVariable* temp_for_last_arg, |
14486 bool is_super_invocation) { | 14546 bool is_super_invocation) { |
14487 UNREACHABLE(); | 14547 UNREACHABLE(); |
14488 return NULL; | 14548 return NULL; |
14489 } | 14549 } |
14490 | 14550 |
14491 } // namespace dart | 14551 } // namespace dart |
14492 | 14552 |
14493 #endif // DART_PRECOMPILED_RUNTIME | 14553 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |