Chromium Code Reviews| Index: src/parsing/parser-base.h |
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
| index 530ce5aa18e37fad2cad1ef13015731c4889ffa7..82aaf8b503fb91df60bfe78232aa1e5091fd5383 100644 |
| --- a/src/parsing/parser-base.h |
| +++ b/src/parsing/parser-base.h |
| @@ -190,6 +190,14 @@ class ParserBase : public Traits { |
| Scope* scope; |
| }; |
| + struct TailCallExpression { |
| + TailCallExpression(ExpressionT expression, int pos) |
| + : expression(expression), pos(pos) {} |
| + |
| + ExpressionT expression; |
| + int pos; |
| + }; |
| + |
| class FunctionState BASE_EMBEDDED { |
| public: |
| FunctionState(FunctionState** function_state_stack, Scope** scope_stack, |
| @@ -247,12 +255,12 @@ class ParserBase : public Traits { |
| return destructuring_assignments_to_rewrite_; |
| } |
| - List<ExpressionT>& expressions_in_tail_position() { |
| + List<TailCallExpression>& expressions_in_tail_position() { |
| return expressions_in_tail_position_; |
| } |
| - void AddExpressionInTailPosition(ExpressionT expression) { |
| + void AddExpressionInTailPosition(ExpressionT expression, int pos) { |
| if (collect_expressions_in_tail_position_) { |
| - expressions_in_tail_position_.Add(expression); |
| + expressions_in_tail_position_.Add(TailCallExpression(expression, pos)); |
| } |
| } |
| @@ -315,7 +323,7 @@ class ParserBase : public Traits { |
| Scope* outer_scope_; |
| List<DestructuringAssignment> destructuring_assignments_to_rewrite_; |
| - List<ExpressionT> expressions_in_tail_position_; |
| + List<TailCallExpression> expressions_in_tail_position_; |
| bool collect_expressions_in_tail_position_; |
| ZoneList<ExpressionT> non_patterns_to_rewrite_; |
| @@ -334,6 +342,42 @@ class ParserBase : public Traits { |
| friend class Checkpoint; |
| }; |
| + // This scope disables collecting of expressions at tail call position. |
| + class DontCollectExpressionsInTailPositionScope { |
| + public: |
| + explicit DontCollectExpressionsInTailPositionScope( |
| + 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: |
| + FunctionState* function_state_; |
| + bool old_value_; |
| + }; |
| + |
| + // Collects all return expressions at tail call position in this scope |
| + // to a separate list. |
| + class CollectExpressionsInTailPositionToListScope { |
| + public: |
| + CollectExpressionsInTailPositionToListScope(FunctionState* function_state, |
| + List<TailCallExpression>* 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: |
| + FunctionState* function_state_; |
| + List<TailCallExpression>* list_; |
| + }; |
| + |
| // Annoyingly, arrow functions first parse as comma expressions, then when we |
| // see the => we have to go back and reinterpret the arguments as being formal |
| // parameters. To do so we need to reset some of the parser state back to |
| @@ -1892,6 +1936,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| // ArrowFunction |
| // YieldExpression |
| // LeftHandSideExpression AssignmentOperator AssignmentExpression |
| + // TailCallExpression |
| bool is_destructuring_assignment = false; |
| int lhs_beg_pos = peek_position(); |
| @@ -2858,6 +2903,22 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
| // Single-expression body |
| int pos = position(); |
| ExpressionClassifier classifier(this); |
| + bool is_tail_call_expression; |
| + if (FLAG_harmony_explicit_tailcalls) { |
| + // TODO(ishell): update chapter number. |
| + // ES7 XX.YY.ZZ |
| + if (peek() == Token::CONTINUE) { |
| + Consume(Token::CONTINUE); |
| + pos = position(); |
| + is_tail_call_expression = true; |
| + } else { |
| + is_tail_call_expression = false; |
| + } |
| + } else { |
| + // ES6 14.6.1 Static Semantics: IsInTailPosition |
| + is_tail_call_expression = |
| + allow_tailcalls() && !is_sloppy(language_mode()); |
| + } |
| ExpressionT expression = |
| ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK); |
| Traits::RewriteNonPattern(&classifier, CHECK_OK); |
| @@ -2866,8 +2927,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
| body->Add(factory()->NewReturnStatement(expression, pos), zone()); |
| materialized_literal_count = function_state.materialized_literal_count(); |
| expected_property_count = function_state.expected_property_count(); |
| - // ES6 14.6.1 Static Semantics: IsInTailPosition |
| - if (allow_tailcalls() && !is_sloppy(language_mode())) { |
| + if (is_tail_call_expression) { |
|
rossberg
2016/04/26 14:56:57
Nit: why separate this from the rest of the logic?
Igor Sheludko
2016/04/26 16:48:17
I'll address this in a follow-up CL when I introdu
|
| this->MarkTailPosition(expression); |
| } |
| } |