| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index 6e05fcbb01798e39b4ba719fd1d628552d31e7a7..ea5072e27d7b5c071b0a91ee86db353b3d1e3a31 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -2573,6 +2573,13 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| function_state_->set_return_location(loc);
|
|
|
| Token::Value tok = peek();
|
| + int tail_call_position = -1;
|
| + if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) {
|
| + Consume(Token::CONTINUE);
|
| + tail_call_position = position();
|
| + tok = peek();
|
| + }
|
| +
|
| Statement* result;
|
| Expression* return_value;
|
| if (scanner()->HasAnyLineTerminatorBeforeNext() ||
|
| @@ -2629,9 +2636,21 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| is_object_conditional, pos);
|
| }
|
|
|
| - // ES6 14.6.1 Static Semantics: IsInTailPosition
|
| - if (allow_tailcalls() && !is_sloppy(language_mode())) {
|
| - function_state_->AddExpressionInTailPosition(return_value);
|
| + // TODO(ishell): update chapter number.
|
| + // ES8 XX.YY.ZZ
|
| + if (tail_call_position >= 0) {
|
| + if (!function_state_->collect_expressions_in_tail_position()) {
|
| + Scanner::Location loc(tail_call_position, tail_call_position + 1);
|
| + ReportMessageAt(loc, MessageTemplate::kTailCallInTryBlock);
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| + function_state_->AddExpressionInTailPosition(return_value,
|
| + tail_call_position);
|
| +
|
| + } else if (allow_tailcalls() && !is_sloppy(language_mode())) {
|
| + // ES6 14.6.1 Static Semantics: IsInTailPosition
|
| + function_state_->AddExpressionInTailPosition(return_value, pos);
|
| }
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
| @@ -2811,40 +2830,6 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
|
| factory()->NewThrow(exception, pos), pos);
|
| }
|
|
|
| -class Parser::DontCollectExpressionsInTailPositionScope {
|
| - public:
|
| - DontCollectExpressionsInTailPositionScope(
|
| - Parser::FunctionState* function_state)
|
| - : function_state_(function_state),
|
| - old_value_(function_state->collect_expressions_in_tail_position()) {
|
| - function_state->set_collect_expressions_in_tail_position(false);
|
| - }
|
| - ~DontCollectExpressionsInTailPositionScope() {
|
| - function_state_->set_collect_expressions_in_tail_position(old_value_);
|
| - }
|
| -
|
| - private:
|
| - Parser::FunctionState* function_state_;
|
| - bool old_value_;
|
| -};
|
| -
|
| -// Collects all return expressions at tail call position in this scope
|
| -// to a separate list.
|
| -class Parser::CollectExpressionsInTailPositionToListScope {
|
| - public:
|
| - CollectExpressionsInTailPositionToListScope(
|
| - Parser::FunctionState* function_state, List<Expression*>* list)
|
| - : function_state_(function_state), list_(list) {
|
| - function_state->expressions_in_tail_position().Swap(list_);
|
| - }
|
| - ~CollectExpressionsInTailPositionToListScope() {
|
| - function_state_->expressions_in_tail_position().Swap(list_);
|
| - }
|
| -
|
| - private:
|
| - Parser::FunctionState* function_state_;
|
| - List<Expression*>* list_;
|
| -};
|
|
|
| TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| // TryStatement ::
|
| @@ -2877,7 +2862,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| Scope* catch_scope = NULL;
|
| Variable* catch_variable = NULL;
|
| Block* catch_block = NULL;
|
| - List<Expression*> expressions_in_tail_position_in_catch_block;
|
| + List<TailCallExpression> expressions_in_tail_position_in_catch_block;
|
| if (tok == Token::CATCH) {
|
| Consume(Token::CATCH);
|
|
|
| @@ -2993,6 +2978,16 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| result = factory()->NewTryCatchStatement(try_block, catch_scope,
|
| catch_variable, catch_block, pos);
|
| } else {
|
| + if (FLAG_harmony_explicit_tailcalls &&
|
| + expressions_in_tail_position_in_catch_block.length() > 0) {
|
| + // TODO(ishell): update chapter number.
|
| + // ES8 XX.YY.ZZ
|
| + int pos = expressions_in_tail_position_in_catch_block[0].pos;
|
| + ReportMessageAt(Scanner::Location(pos, pos + 1),
|
| + MessageTemplate::kTailCallInCatchBlock);
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| DCHECK(finally_block != NULL);
|
| result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
|
| }
|
| @@ -4573,10 +4568,10 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
|
|
| // ES6 14.6.1 Static Semantics: IsInTailPosition
|
| // Mark collected return expressions that are in tail call position.
|
| - const List<Expression*>& expressions_in_tail_position =
|
| + const List<TailCallExpression>& expressions_in_tail_position =
|
| function_state_->expressions_in_tail_position();
|
| for (int i = 0; i < expressions_in_tail_position.length(); ++i) {
|
| - MarkTailPosition(expressions_in_tail_position[i]);
|
| + MarkTailPosition(expressions_in_tail_position[i].expression);
|
| }
|
| return result;
|
| }
|
|
|