Chromium Code Reviews| Index: runtime/vm/parser.cc |
| =================================================================== |
| --- runtime/vm/parser.cc (revision 44786) |
| +++ runtime/vm/parser.cc (working copy) |
| @@ -764,18 +764,6 @@ |
| }; |
| -static bool HasReturnNode(SequenceNode* seq) { |
| - if (seq->length() == 0) { |
| - return false; |
| - } else if ((seq->length()) == 1 && |
| - (seq->NodeAt(seq->length() - 1)->IsSequenceNode())) { |
| - return HasReturnNode(seq->NodeAt(seq->length() - 1)->AsSequenceNode()); |
| - } else { |
| - return seq->NodeAt(seq->length() - 1)->IsReturnNode(); |
| - } |
| -} |
| - |
| - |
| void Parser::ParseClass(const Class& cls) { |
| if (!cls.is_synthesized_class()) { |
| Isolate* isolate = Isolate::Current(); |
| @@ -906,16 +894,6 @@ |
| UNREACHABLE(); |
| } |
| - if (!HasReturnNode(node_sequence)) { |
| - // Add implicit return node. The implicit return value of synchronous |
| - // generator closures is false, to indicate that there are no more |
| - // elements in the iterable. In other cases the implicit return value |
| - // is null. |
| - AstNode* return_value = func.IsSyncGenClosure() |
| - ? new LiteralNode(func.end_token_pos(), Bool::False()) |
| - : new LiteralNode(func.end_token_pos(), Instance::ZoneHandle()); |
| - node_sequence->Add(new ReturnNode(func.end_token_pos(), return_value)); |
| - } |
| if (parsed_function->has_expression_temp_var()) { |
| node_sequence->scope()->AddVariable(parsed_function->expression_temp_var()); |
| } |
| @@ -6837,6 +6815,37 @@ |
| } |
| +// This is called for the compiled function's outermost node sequence. |
| +// Ensure that the node sequence S containing the function's code ends |
| +// with a return statement. S may be a child sequence of seq. |
|
regis
2015/03/31 18:44:41
The comment does not explain the logic implemented
|
| +void Parser::EnsureHasReturnNode(SequenceNode* seq) { |
| + // Find innermost child sequence that ends at the same token position. |
| + while ((seq->length() == 1) && (seq->NodeAt(0)->IsSequenceNode())) { |
| + SequenceNode* child = seq->NodeAt(0)->AsSequenceNode(); |
| + if ((seq->scope() != NULL) && |
| + (child->scope() != NULL) && |
| + (seq->scope()->end_token_pos() == child->scope()->end_token_pos())) { |
| + seq = child; |
| + } else { |
| + break; |
| + } |
| + } |
| + // Add a return node if necessary. |
| + if ((seq->length() == 0) || |
| + !seq->NodeAt(seq->length() - 1)->IsReturnNode()) { |
| + // The implicit return value of synchronous generator closures is false, |
| + // to indicate that there are no more elements in the iterable. |
| + // In other cases the implicit return value is null. |
| + ASSERT(current_function().raw() == innermost_function().raw()); |
| + const Function& func = current_function(); |
| + AstNode* return_value = func.IsSyncGenClosure() |
| + ? new LiteralNode(func.end_token_pos(), Bool::False()) |
| + : new LiteralNode(func.end_token_pos(), Instance::ZoneHandle()); |
| + seq->Add(new ReturnNode(func.end_token_pos(), return_value)); |
| + } |
| +} |
| + |
| + |
| SequenceNode* Parser::CloseBlock() { |
| SequenceNode* statements = current_block_->statements; |
| if (current_block_->scope != NULL) { |
| @@ -6846,6 +6855,10 @@ |
| current_block_->scope->set_end_token_pos(TokenPos()); |
| } |
| current_block_ = current_block_->parent; |
| + if (current_block_ == NULL) { |
| + ASSERT(statements != NULL); |
| + EnsureHasReturnNode(statements); |
|
regis
2015/03/31 18:44:41
This does not feel right to me. Closing a block sh
|
| + } |
| return statements; |
| } |