OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-expression-rewriter.h" | 9 #include "src/ast/ast-expression-rewriter.h" |
10 #include "src/ast/ast-expression-visitor.h" | 10 #include "src/ast/ast-expression-visitor.h" |
(...skipping 2555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2566 // 'return' Expression? ';' | 2566 // 'return' Expression? ';' |
2567 | 2567 |
2568 // Consume the return token. It is necessary to do that before | 2568 // Consume the return token. It is necessary to do that before |
2569 // reporting any errors on it, because of the way errors are | 2569 // reporting any errors on it, because of the way errors are |
2570 // reported (underlining). | 2570 // reported (underlining). |
2571 Expect(Token::RETURN, CHECK_OK); | 2571 Expect(Token::RETURN, CHECK_OK); |
2572 Scanner::Location loc = scanner()->location(); | 2572 Scanner::Location loc = scanner()->location(); |
2573 function_state_->set_return_location(loc); | 2573 function_state_->set_return_location(loc); |
2574 | 2574 |
2575 Token::Value tok = peek(); | 2575 Token::Value tok = peek(); |
| 2576 int tail_call_position = -1; |
| 2577 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) { |
| 2578 Consume(Token::CONTINUE); |
| 2579 tail_call_position = position(); |
| 2580 tok = peek(); |
| 2581 } |
| 2582 |
2576 Statement* result; | 2583 Statement* result; |
2577 Expression* return_value; | 2584 Expression* return_value; |
2578 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 2585 if (scanner()->HasAnyLineTerminatorBeforeNext() || |
2579 tok == Token::SEMICOLON || | 2586 tok == Token::SEMICOLON || |
2580 tok == Token::RBRACE || | 2587 tok == Token::RBRACE || |
2581 tok == Token::EOS) { | 2588 tok == Token::EOS) { |
2582 if (IsSubclassConstructor(function_state_->kind())) { | 2589 if (IsSubclassConstructor(function_state_->kind())) { |
2583 return_value = ThisExpression(scope_, factory(), loc.beg_pos); | 2590 return_value = ThisExpression(scope_, factory(), loc.beg_pos); |
2584 } else { | 2591 } else { |
2585 return_value = GetLiteralUndefined(position()); | 2592 return_value = GetLiteralUndefined(position()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2622 Expression* is_undefined = factory()->NewCompareOperation( | 2629 Expression* is_undefined = factory()->NewCompareOperation( |
2623 Token::EQ_STRICT, assign, | 2630 Token::EQ_STRICT, assign, |
2624 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); | 2631 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); |
2625 | 2632 |
2626 // is_undefined ? this : is_object_conditional | 2633 // is_undefined ? this : is_object_conditional |
2627 return_value = factory()->NewConditional( | 2634 return_value = factory()->NewConditional( |
2628 is_undefined, ThisExpression(scope_, factory(), pos), | 2635 is_undefined, ThisExpression(scope_, factory(), pos), |
2629 is_object_conditional, pos); | 2636 is_object_conditional, pos); |
2630 } | 2637 } |
2631 | 2638 |
2632 // ES6 14.6.1 Static Semantics: IsInTailPosition | 2639 // TODO(ishell): update chapter number. |
2633 if (allow_tailcalls() && !is_sloppy(language_mode())) { | 2640 // ES8 XX.YY.ZZ |
2634 function_state_->AddExpressionInTailPosition(return_value); | 2641 if (tail_call_position >= 0) { |
| 2642 if (!function_state_->collect_expressions_in_tail_position()) { |
| 2643 Scanner::Location loc(tail_call_position, tail_call_position + 1); |
| 2644 ReportMessageAt(loc, MessageTemplate::kTailCallInTryBlock); |
| 2645 *ok = false; |
| 2646 return NULL; |
| 2647 } |
| 2648 function_state_->AddExpressionInTailPosition(return_value, |
| 2649 tail_call_position); |
| 2650 |
| 2651 } else if (allow_tailcalls() && !is_sloppy(language_mode())) { |
| 2652 // ES6 14.6.1 Static Semantics: IsInTailPosition |
| 2653 function_state_->AddExpressionInTailPosition(return_value, pos); |
2635 } | 2654 } |
2636 } | 2655 } |
2637 ExpectSemicolon(CHECK_OK); | 2656 ExpectSemicolon(CHECK_OK); |
2638 | 2657 |
2639 if (is_generator()) { | 2658 if (is_generator()) { |
2640 return_value = BuildIteratorResult(return_value, true); | 2659 return_value = BuildIteratorResult(return_value, true); |
2641 } | 2660 } |
2642 | 2661 |
2643 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2662 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
2644 | 2663 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2804 *ok = false; | 2823 *ok = false; |
2805 return NULL; | 2824 return NULL; |
2806 } | 2825 } |
2807 Expression* exception = ParseExpression(true, CHECK_OK); | 2826 Expression* exception = ParseExpression(true, CHECK_OK); |
2808 ExpectSemicolon(CHECK_OK); | 2827 ExpectSemicolon(CHECK_OK); |
2809 | 2828 |
2810 return factory()->NewExpressionStatement( | 2829 return factory()->NewExpressionStatement( |
2811 factory()->NewThrow(exception, pos), pos); | 2830 factory()->NewThrow(exception, pos), pos); |
2812 } | 2831 } |
2813 | 2832 |
2814 class Parser::DontCollectExpressionsInTailPositionScope { | |
2815 public: | |
2816 DontCollectExpressionsInTailPositionScope( | |
2817 Parser::FunctionState* function_state) | |
2818 : function_state_(function_state), | |
2819 old_value_(function_state->collect_expressions_in_tail_position()) { | |
2820 function_state->set_collect_expressions_in_tail_position(false); | |
2821 } | |
2822 ~DontCollectExpressionsInTailPositionScope() { | |
2823 function_state_->set_collect_expressions_in_tail_position(old_value_); | |
2824 } | |
2825 | |
2826 private: | |
2827 Parser::FunctionState* function_state_; | |
2828 bool old_value_; | |
2829 }; | |
2830 | |
2831 // Collects all return expressions at tail call position in this scope | |
2832 // to a separate list. | |
2833 class Parser::CollectExpressionsInTailPositionToListScope { | |
2834 public: | |
2835 CollectExpressionsInTailPositionToListScope( | |
2836 Parser::FunctionState* function_state, List<Expression*>* list) | |
2837 : function_state_(function_state), list_(list) { | |
2838 function_state->expressions_in_tail_position().Swap(list_); | |
2839 } | |
2840 ~CollectExpressionsInTailPositionToListScope() { | |
2841 function_state_->expressions_in_tail_position().Swap(list_); | |
2842 } | |
2843 | |
2844 private: | |
2845 Parser::FunctionState* function_state_; | |
2846 List<Expression*>* list_; | |
2847 }; | |
2848 | 2833 |
2849 TryStatement* Parser::ParseTryStatement(bool* ok) { | 2834 TryStatement* Parser::ParseTryStatement(bool* ok) { |
2850 // TryStatement :: | 2835 // TryStatement :: |
2851 // 'try' Block Catch | 2836 // 'try' Block Catch |
2852 // 'try' Block Finally | 2837 // 'try' Block Finally |
2853 // 'try' Block Catch Finally | 2838 // 'try' Block Catch Finally |
2854 // | 2839 // |
2855 // Catch :: | 2840 // Catch :: |
2856 // 'catch' '(' Identifier ')' Block | 2841 // 'catch' '(' Identifier ')' Block |
2857 // | 2842 // |
(...skipping 12 matching lines...) Expand all Loading... |
2870 Token::Value tok = peek(); | 2855 Token::Value tok = peek(); |
2871 if (tok != Token::CATCH && tok != Token::FINALLY) { | 2856 if (tok != Token::CATCH && tok != Token::FINALLY) { |
2872 ReportMessage(MessageTemplate::kNoCatchOrFinally); | 2857 ReportMessage(MessageTemplate::kNoCatchOrFinally); |
2873 *ok = false; | 2858 *ok = false; |
2874 return NULL; | 2859 return NULL; |
2875 } | 2860 } |
2876 | 2861 |
2877 Scope* catch_scope = NULL; | 2862 Scope* catch_scope = NULL; |
2878 Variable* catch_variable = NULL; | 2863 Variable* catch_variable = NULL; |
2879 Block* catch_block = NULL; | 2864 Block* catch_block = NULL; |
2880 List<Expression*> expressions_in_tail_position_in_catch_block; | 2865 List<TailCallExpression> expressions_in_tail_position_in_catch_block; |
2881 if (tok == Token::CATCH) { | 2866 if (tok == Token::CATCH) { |
2882 Consume(Token::CATCH); | 2867 Consume(Token::CATCH); |
2883 | 2868 |
2884 Expect(Token::LPAREN, CHECK_OK); | 2869 Expect(Token::LPAREN, CHECK_OK); |
2885 catch_scope = NewScope(scope_, CATCH_SCOPE); | 2870 catch_scope = NewScope(scope_, CATCH_SCOPE); |
2886 catch_scope->set_start_position(scanner()->location().beg_pos); | 2871 catch_scope->set_start_position(scanner()->location().beg_pos); |
2887 | 2872 |
2888 ExpressionClassifier pattern_classifier(this); | 2873 ExpressionClassifier pattern_classifier(this); |
2889 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 2874 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
2890 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 2875 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2986 // For a try-catch construct append return expressions from the catch block | 2971 // For a try-catch construct append return expressions from the catch block |
2987 // to the list of return expressions. | 2972 // to the list of return expressions. |
2988 function_state_->expressions_in_tail_position().AddAll( | 2973 function_state_->expressions_in_tail_position().AddAll( |
2989 expressions_in_tail_position_in_catch_block); | 2974 expressions_in_tail_position_in_catch_block); |
2990 | 2975 |
2991 DCHECK(finally_block == NULL); | 2976 DCHECK(finally_block == NULL); |
2992 DCHECK(catch_scope != NULL && catch_variable != NULL); | 2977 DCHECK(catch_scope != NULL && catch_variable != NULL); |
2993 result = factory()->NewTryCatchStatement(try_block, catch_scope, | 2978 result = factory()->NewTryCatchStatement(try_block, catch_scope, |
2994 catch_variable, catch_block, pos); | 2979 catch_variable, catch_block, pos); |
2995 } else { | 2980 } else { |
| 2981 if (FLAG_harmony_explicit_tailcalls && |
| 2982 expressions_in_tail_position_in_catch_block.length() > 0) { |
| 2983 // TODO(ishell): update chapter number. |
| 2984 // ES8 XX.YY.ZZ |
| 2985 int pos = expressions_in_tail_position_in_catch_block[0].pos; |
| 2986 ReportMessageAt(Scanner::Location(pos, pos + 1), |
| 2987 MessageTemplate::kTailCallInCatchBlock); |
| 2988 *ok = false; |
| 2989 return NULL; |
| 2990 } |
2996 DCHECK(finally_block != NULL); | 2991 DCHECK(finally_block != NULL); |
2997 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); | 2992 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); |
2998 } | 2993 } |
2999 | 2994 |
3000 return result; | 2995 return result; |
3001 } | 2996 } |
3002 | 2997 |
3003 | 2998 |
3004 DoWhileStatement* Parser::ParseDoWhileStatement( | 2999 DoWhileStatement* Parser::ParseDoWhileStatement( |
3005 ZoneList<const AstRawString*>* labels, bool* ok) { | 3000 ZoneList<const AstRawString*>* labels, bool* ok) { |
(...skipping 1560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4566 result->Set(kFunctionNameAssignmentIndex, | 4561 result->Set(kFunctionNameAssignmentIndex, |
4567 factory()->NewExpressionStatement( | 4562 factory()->NewExpressionStatement( |
4568 factory()->NewAssignment(Token::INIT, fproxy, | 4563 factory()->NewAssignment(Token::INIT, fproxy, |
4569 factory()->NewThisFunction(pos), | 4564 factory()->NewThisFunction(pos), |
4570 RelocInfo::kNoPosition), | 4565 RelocInfo::kNoPosition), |
4571 RelocInfo::kNoPosition)); | 4566 RelocInfo::kNoPosition)); |
4572 } | 4567 } |
4573 | 4568 |
4574 // ES6 14.6.1 Static Semantics: IsInTailPosition | 4569 // ES6 14.6.1 Static Semantics: IsInTailPosition |
4575 // Mark collected return expressions that are in tail call position. | 4570 // Mark collected return expressions that are in tail call position. |
4576 const List<Expression*>& expressions_in_tail_position = | 4571 const List<TailCallExpression>& expressions_in_tail_position = |
4577 function_state_->expressions_in_tail_position(); | 4572 function_state_->expressions_in_tail_position(); |
4578 for (int i = 0; i < expressions_in_tail_position.length(); ++i) { | 4573 for (int i = 0; i < expressions_in_tail_position.length(); ++i) { |
4579 MarkTailPosition(expressions_in_tail_position[i]); | 4574 MarkTailPosition(expressions_in_tail_position[i].expression); |
4580 } | 4575 } |
4581 return result; | 4576 return result; |
4582 } | 4577 } |
4583 | 4578 |
4584 | 4579 |
4585 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4580 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
4586 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { | 4581 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { |
4587 // This function may be called on a background thread too; record only the | 4582 // This function may be called on a background thread too; record only the |
4588 // main thread preparse times. | 4583 // main thread preparse times. |
4589 if (pre_parse_timer_ != NULL) { | 4584 if (pre_parse_timer_ != NULL) { |
(...skipping 2206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6796 try_block, target); | 6791 try_block, target); |
6797 final_loop = target; | 6792 final_loop = target; |
6798 } | 6793 } |
6799 | 6794 |
6800 return final_loop; | 6795 return final_loop; |
6801 } | 6796 } |
6802 | 6797 |
6803 | 6798 |
6804 } // namespace internal | 6799 } // namespace internal |
6805 } // namespace v8 | 6800 } // namespace v8 |
OLD | NEW |