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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 // reported (underlining). | 694 // reported (underlining). |
695 Expect(Token::RETURN, CHECK_OK); | 695 Expect(Token::RETURN, CHECK_OK); |
696 function_state_->set_return_location(scanner()->location()); | 696 function_state_->set_return_location(scanner()->location()); |
697 | 697 |
698 // An ECMAScript program is considered syntactically incorrect if it | 698 // An ECMAScript program is considered syntactically incorrect if it |
699 // contains a return statement that is not within the body of a | 699 // contains a return statement that is not within the body of a |
700 // function. See ECMA-262, section 12.9, page 67. | 700 // function. See ECMA-262, section 12.9, page 67. |
701 // This is not handled during preparsing. | 701 // This is not handled during preparsing. |
702 | 702 |
703 Token::Value tok = peek(); | 703 Token::Value tok = peek(); |
704 int tail_call_position = -1; | |
705 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) { | |
706 Consume(Token::CONTINUE); | |
707 tail_call_position = position(); | |
708 tok = peek(); | |
709 } | |
710 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 704 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
711 tok != Token::SEMICOLON && | 705 tok != Token::SEMICOLON && |
712 tok != Token::RBRACE && | 706 tok != Token::RBRACE && |
713 tok != Token::EOS) { | 707 tok != Token::EOS) { |
| 708 // Because of the return code rewriting that happens in case of a subclass |
| 709 // constructor we don't want to accept tail calls, therefore we don't set |
| 710 // ReturnExprScope to kInsideValidReturnStatement here. |
| 711 ReturnExprContext return_expr_context = |
| 712 IsSubclassConstructor(function_state_->kind()) |
| 713 ? function_state_->return_expr_context() |
| 714 : ReturnExprContext::kInsideValidReturnStatement; |
| 715 |
| 716 ReturnExprScope maybe_allow_tail_calls(function_state_, |
| 717 return_expr_context); |
714 ParseExpression(true, CHECK_OK); | 718 ParseExpression(true, CHECK_OK); |
715 if (tail_call_position >= 0) { | |
716 ReturnExprContext return_expr_context = | |
717 function_state_->return_expr_context(); | |
718 if (return_expr_context != ReturnExprContext::kNormal) { | |
719 ReportIllegalTailCallAt(tail_call_position, return_expr_context); | |
720 *ok = false; | |
721 return Statement::Default(); | |
722 } | |
723 function_state_->AddExpressionInTailPosition( | |
724 PreParserExpression::Default(), tail_call_position); | |
725 } | |
726 } | 719 } |
727 ExpectSemicolon(CHECK_OK); | 720 ExpectSemicolon(CHECK_OK); |
728 return Statement::Jump(); | 721 return Statement::Jump(); |
729 } | 722 } |
730 | 723 |
731 | 724 |
732 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { | 725 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
733 // WithStatement :: | 726 // WithStatement :: |
734 // 'with' '(' Expression ')' Statement | 727 // 'with' '(' Expression ')' Statement |
735 Expect(Token::WITH, CHECK_OK); | 728 Expect(Token::WITH, CHECK_OK); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 ReturnExprContext::kInsideTryBlock); | 975 ReturnExprContext::kInsideTryBlock); |
983 ParseBlock(CHECK_OK); | 976 ParseBlock(CHECK_OK); |
984 } | 977 } |
985 | 978 |
986 Token::Value tok = peek(); | 979 Token::Value tok = peek(); |
987 if (tok != Token::CATCH && tok != Token::FINALLY) { | 980 if (tok != Token::CATCH && tok != Token::FINALLY) { |
988 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); | 981 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); |
989 *ok = false; | 982 *ok = false; |
990 return Statement::Default(); | 983 return Statement::Default(); |
991 } | 984 } |
992 List<TailCallExpression> expressions_in_tail_position_in_catch_block; | 985 TailCallExpressionList tail_call_expressions_in_catch_block(zone()); |
993 bool catch_block_exists = false; | 986 bool catch_block_exists = false; |
994 if (tok == Token::CATCH) { | 987 if (tok == Token::CATCH) { |
995 Consume(Token::CATCH); | 988 Consume(Token::CATCH); |
996 Expect(Token::LPAREN, CHECK_OK); | 989 Expect(Token::LPAREN, CHECK_OK); |
997 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); | 990 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); |
998 ExpressionClassifier pattern_classifier(this); | 991 ExpressionClassifier pattern_classifier(this); |
999 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 992 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
1000 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 993 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
1001 Expect(Token::RPAREN, CHECK_OK); | 994 Expect(Token::RPAREN, CHECK_OK); |
1002 { | 995 { |
1003 CollectExpressionsInTailPositionToListScope | 996 CollectExpressionsInTailPositionToListScope |
1004 collect_expressions_in_tail_position_scope( | 997 collect_tail_call_expressions_scope( |
1005 function_state_, &expressions_in_tail_position_in_catch_block); | 998 function_state_, &tail_call_expressions_in_catch_block); |
1006 BlockState block_state(&scope_, catch_scope); | 999 BlockState block_state(&scope_, catch_scope); |
1007 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 1000 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
1008 { | 1001 { |
1009 BlockState block_state(&scope_, block_scope); | 1002 BlockState block_state(&scope_, block_scope); |
1010 ParseBlock(CHECK_OK); | 1003 ParseBlock(CHECK_OK); |
1011 } | 1004 } |
1012 } | 1005 } |
1013 catch_block_exists = true; | 1006 catch_block_exists = true; |
1014 tok = peek(); | 1007 tok = peek(); |
1015 } | 1008 } |
1016 if (tok == Token::FINALLY) { | 1009 if (tok == Token::FINALLY) { |
1017 Consume(Token::FINALLY); | 1010 Consume(Token::FINALLY); |
1018 ParseBlock(CHECK_OK); | 1011 ParseBlock(CHECK_OK); |
1019 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && | 1012 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && |
1020 expressions_in_tail_position_in_catch_block.length() > 0) { | 1013 !tail_call_expressions_in_catch_block.is_empty()) { |
1021 // TODO(ishell): update chapter number. | 1014 // TODO(ishell): update chapter number. |
1022 // ES8 XX.YY.ZZ | 1015 // ES8 XX.YY.ZZ |
1023 int pos = expressions_in_tail_position_in_catch_block[0].pos; | 1016 ReportMessageAt(tail_call_expressions_in_catch_block.location(), |
1024 ReportMessageAt(Scanner::Location(pos, pos + 1), | 1017 MessageTemplate::kUnexpectedTailCallInCatchBlock); |
1025 MessageTemplate::kTailCallInCatchBlock); | |
1026 *ok = false; | 1018 *ok = false; |
1027 return Statement::Default(); | 1019 return Statement::Default(); |
1028 } | 1020 } |
1029 } | 1021 } |
1030 return Statement::Default(); | 1022 return Statement::Default(); |
1031 } | 1023 } |
1032 | 1024 |
1033 | 1025 |
1034 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { | 1026 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
1035 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 1027 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 Scope* scope = NewScope(scope_, BLOCK_SCOPE); | 1144 Scope* scope = NewScope(scope_, BLOCK_SCOPE); |
1153 BlockState block_state(&scope_, scope); | 1145 BlockState block_state(&scope_, scope); |
1154 scope_->SetLanguageMode( | 1146 scope_->SetLanguageMode( |
1155 static_cast<LanguageMode>(class_language_mode | STRICT)); | 1147 static_cast<LanguageMode>(class_language_mode | STRICT)); |
1156 // TODO(marja): Make PreParser use scope names too. | 1148 // TODO(marja): Make PreParser use scope names too. |
1157 // scope_->SetScopeName(name); | 1149 // scope_->SetScopeName(name); |
1158 | 1150 |
1159 bool has_extends = Check(Token::EXTENDS); | 1151 bool has_extends = Check(Token::EXTENDS); |
1160 if (has_extends) { | 1152 if (has_extends) { |
1161 ExpressionClassifier classifier(this); | 1153 ExpressionClassifier classifier(this); |
1162 ParseLeftHandSideExpression(&classifier, CHECK_OK); | 1154 ParseLeftHandSideExpression(kDontAcceptTCE, &classifier, CHECK_OK); |
1163 ValidateExpression(&classifier, CHECK_OK); | 1155 ValidateExpression(&classifier, CHECK_OK); |
1164 } | 1156 } |
1165 | 1157 |
1166 ClassLiteralChecker checker(this); | 1158 ClassLiteralChecker checker(this); |
1167 bool has_seen_constructor = false; | 1159 bool has_seen_constructor = false; |
1168 | 1160 |
1169 Expect(Token::LBRACE, CHECK_OK); | 1161 Expect(Token::LBRACE, CHECK_OK); |
1170 while (peek() != Token::RBRACE) { | 1162 while (peek() != Token::RBRACE) { |
1171 if (Check(Token::SEMICOLON)) continue; | 1163 if (Check(Token::SEMICOLON)) continue; |
1172 const bool in_class = true; | 1164 const bool in_class = true; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 } | 1210 } |
1219 Expect(Token::RBRACE, CHECK_OK); | 1211 Expect(Token::RBRACE, CHECK_OK); |
1220 return PreParserExpression::Default(); | 1212 return PreParserExpression::Default(); |
1221 } | 1213 } |
1222 | 1214 |
1223 #undef CHECK_OK | 1215 #undef CHECK_OK |
1224 | 1216 |
1225 | 1217 |
1226 } // namespace internal | 1218 } // namespace internal |
1227 } // namespace v8 | 1219 } // namespace v8 |
OLD | NEW |