OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 <cmath> | 5 #include <cmath> |
6 | 6 |
7 #include "src/allocation.h" | 7 #include "src/allocation.h" |
8 #include "src/base/logging.h" | 8 #include "src/base/logging.h" |
9 #include "src/conversions-inl.h" | 9 #include "src/conversions-inl.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 // reported (underlining). | 699 // reported (underlining). |
700 Expect(Token::RETURN, CHECK_OK); | 700 Expect(Token::RETURN, CHECK_OK); |
701 function_state_->set_return_location(scanner()->location()); | 701 function_state_->set_return_location(scanner()->location()); |
702 | 702 |
703 // An ECMAScript program is considered syntactically incorrect if it | 703 // An ECMAScript program is considered syntactically incorrect if it |
704 // contains a return statement that is not within the body of a | 704 // contains a return statement that is not within the body of a |
705 // function. See ECMA-262, section 12.9, page 67. | 705 // function. See ECMA-262, section 12.9, page 67. |
706 // This is not handled during preparsing. | 706 // This is not handled during preparsing. |
707 | 707 |
708 Token::Value tok = peek(); | 708 Token::Value tok = peek(); |
709 int tail_call_position = -1; | |
710 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) { | |
711 Consume(Token::CONTINUE); | |
712 tail_call_position = position(); | |
713 tok = peek(); | |
714 } | |
715 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 709 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
716 tok != Token::SEMICOLON && | 710 tok != Token::SEMICOLON && |
717 tok != Token::RBRACE && | 711 tok != Token::RBRACE && |
718 tok != Token::EOS) { | 712 tok != Token::EOS) { |
| 713 // Because of the return code rewriting that happens in case of a subclass |
| 714 // constructor we don't want to accept tail calls, therefore we don't set |
| 715 // ReturnExprScope to kInsideValidReturnStatement here. |
| 716 ReturnExprContext return_expr_context = |
| 717 IsSubclassConstructor(function_state_->kind()) |
| 718 ? function_state_->return_expr_context() |
| 719 : ReturnExprContext::kInsideValidReturnStatement; |
| 720 |
| 721 ReturnExprScope maybe_allow_tail_calls(function_state_, |
| 722 return_expr_context); |
719 ParseExpression(true, CHECK_OK); | 723 ParseExpression(true, CHECK_OK); |
720 if (tail_call_position >= 0) { | |
721 ReturnExprContext return_expr_context = | |
722 function_state_->return_expr_context(); | |
723 if (return_expr_context != ReturnExprContext::kNormal) { | |
724 ReportIllegalTailCallAt(tail_call_position, return_expr_context); | |
725 *ok = false; | |
726 return Statement::Default(); | |
727 } | |
728 function_state_->AddExpressionInTailPosition( | |
729 PreParserExpression::Default(), tail_call_position); | |
730 } | |
731 } | 724 } |
732 ExpectSemicolon(CHECK_OK); | 725 ExpectSemicolon(CHECK_OK); |
733 return Statement::Jump(); | 726 return Statement::Jump(); |
734 } | 727 } |
735 | 728 |
736 | 729 |
737 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { | 730 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
738 // WithStatement :: | 731 // WithStatement :: |
739 // 'with' '(' Expression ')' Statement | 732 // 'with' '(' Expression ')' Statement |
740 Expect(Token::WITH, CHECK_OK); | 733 Expect(Token::WITH, CHECK_OK); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 ReturnExprContext::kInsideTryBlock); | 980 ReturnExprContext::kInsideTryBlock); |
988 ParseBlock(CHECK_OK); | 981 ParseBlock(CHECK_OK); |
989 } | 982 } |
990 | 983 |
991 Token::Value tok = peek(); | 984 Token::Value tok = peek(); |
992 if (tok != Token::CATCH && tok != Token::FINALLY) { | 985 if (tok != Token::CATCH && tok != Token::FINALLY) { |
993 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); | 986 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); |
994 *ok = false; | 987 *ok = false; |
995 return Statement::Default(); | 988 return Statement::Default(); |
996 } | 989 } |
997 List<TailCallExpression> expressions_in_tail_position_in_catch_block; | 990 TailCallExpressionList tail_call_expressions_in_catch_block(zone()); |
998 bool catch_block_exists = false; | 991 bool catch_block_exists = false; |
999 if (tok == Token::CATCH) { | 992 if (tok == Token::CATCH) { |
1000 Consume(Token::CATCH); | 993 Consume(Token::CATCH); |
1001 Expect(Token::LPAREN, CHECK_OK); | 994 Expect(Token::LPAREN, CHECK_OK); |
1002 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); | 995 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); |
1003 ExpressionClassifier pattern_classifier(this); | 996 ExpressionClassifier pattern_classifier(this); |
1004 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 997 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
1005 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 998 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
1006 Expect(Token::RPAREN, CHECK_OK); | 999 Expect(Token::RPAREN, CHECK_OK); |
1007 { | 1000 { |
1008 CollectExpressionsInTailPositionToListScope | 1001 CollectExpressionsInTailPositionToListScope |
1009 collect_expressions_in_tail_position_scope( | 1002 collect_tail_call_expressions_scope( |
1010 function_state_, &expressions_in_tail_position_in_catch_block); | 1003 function_state_, &tail_call_expressions_in_catch_block); |
1011 BlockState block_state(&scope_, catch_scope); | 1004 BlockState block_state(&scope_, catch_scope); |
1012 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 1005 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
1013 { | 1006 { |
1014 BlockState block_state(&scope_, block_scope); | 1007 BlockState block_state(&scope_, block_scope); |
1015 ParseBlock(CHECK_OK); | 1008 ParseBlock(CHECK_OK); |
1016 } | 1009 } |
1017 } | 1010 } |
1018 catch_block_exists = true; | 1011 catch_block_exists = true; |
1019 tok = peek(); | 1012 tok = peek(); |
1020 } | 1013 } |
1021 if (tok == Token::FINALLY) { | 1014 if (tok == Token::FINALLY) { |
1022 Consume(Token::FINALLY); | 1015 Consume(Token::FINALLY); |
1023 ParseBlock(CHECK_OK); | 1016 ParseBlock(CHECK_OK); |
1024 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && | 1017 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && |
1025 expressions_in_tail_position_in_catch_block.length() > 0) { | 1018 !tail_call_expressions_in_catch_block.is_empty()) { |
1026 // TODO(ishell): update chapter number. | 1019 // TODO(ishell): update chapter number. |
1027 // ES8 XX.YY.ZZ | 1020 // ES8 XX.YY.ZZ |
1028 int pos = expressions_in_tail_position_in_catch_block[0].pos; | 1021 ReportMessageAt(tail_call_expressions_in_catch_block.location(), |
1029 ReportMessageAt(Scanner::Location(pos, pos + 1), | 1022 MessageTemplate::kUnexpectedTailCallInCatchBlock); |
1030 MessageTemplate::kTailCallInCatchBlock); | |
1031 *ok = false; | 1023 *ok = false; |
1032 return Statement::Default(); | 1024 return Statement::Default(); |
1033 } | 1025 } |
1034 } | 1026 } |
1035 return Statement::Default(); | 1027 return Statement::Default(); |
1036 } | 1028 } |
1037 | 1029 |
1038 | 1030 |
1039 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { | 1031 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
1040 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 1032 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 BlockState block_state(&scope_, scope); | 1150 BlockState block_state(&scope_, scope); |
1159 scope_->SetLanguageMode( | 1151 scope_->SetLanguageMode( |
1160 static_cast<LanguageMode>(class_language_mode | STRICT)); | 1152 static_cast<LanguageMode>(class_language_mode | STRICT)); |
1161 // TODO(marja): Make PreParser use scope names too. | 1153 // TODO(marja): Make PreParser use scope names too. |
1162 // scope_->SetScopeName(name); | 1154 // scope_->SetScopeName(name); |
1163 | 1155 |
1164 bool has_extends = Check(Token::EXTENDS); | 1156 bool has_extends = Check(Token::EXTENDS); |
1165 if (has_extends) { | 1157 if (has_extends) { |
1166 ExpressionClassifier extends_classifier(this); | 1158 ExpressionClassifier extends_classifier(this); |
1167 ParseLeftHandSideExpression(&extends_classifier, CHECK_OK); | 1159 ParseLeftHandSideExpression(&extends_classifier, CHECK_OK); |
| 1160 CheckNoTailCallExpressions(&extends_classifier, CHECK_OK); |
1168 ValidateExpression(&extends_classifier, CHECK_OK); | 1161 ValidateExpression(&extends_classifier, CHECK_OK); |
1169 if (classifier != nullptr) { | 1162 if (classifier != nullptr) { |
1170 classifier->Accumulate(&extends_classifier, | 1163 classifier->Accumulate(&extends_classifier, |
1171 ExpressionClassifier::ExpressionProductions); | 1164 ExpressionClassifier::ExpressionProductions); |
1172 } | 1165 } |
1173 } | 1166 } |
1174 | 1167 |
1175 ClassLiteralChecker checker(this); | 1168 ClassLiteralChecker checker(this); |
1176 bool has_seen_constructor = false; | 1169 bool has_seen_constructor = false; |
1177 | 1170 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 } | 1220 } |
1228 Expect(Token::RBRACE, CHECK_OK); | 1221 Expect(Token::RBRACE, CHECK_OK); |
1229 return PreParserExpression::Default(); | 1222 return PreParserExpression::Default(); |
1230 } | 1223 } |
1231 | 1224 |
1232 #undef CHECK_OK | 1225 #undef CHECK_OK |
1233 | 1226 |
1234 | 1227 |
1235 } // namespace internal | 1228 } // namespace internal |
1236 } // namespace v8 | 1229 } // namespace v8 |
OLD | NEW |