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" |
11 #include "src/globals.h" | 11 #include "src/globals.h" |
12 #include "src/hashmap.h" | 12 #include "src/hashmap.h" |
13 #include "src/list.h" | 13 #include "src/list.h" |
14 #include "src/parsing/parser-base.h" | 14 #include "src/parsing/parser-base.h" |
| 15 #include "src/parsing/preparse-data-format.h" |
15 #include "src/parsing/preparse-data.h" | 16 #include "src/parsing/preparse-data.h" |
16 #include "src/parsing/preparse-data-format.h" | |
17 #include "src/parsing/preparser.h" | 17 #include "src/parsing/preparser.h" |
18 #include "src/unicode.h" | 18 #include "src/unicode.h" |
19 #include "src/utils.h" | 19 #include "src/utils.h" |
20 | 20 |
21 namespace v8 { | 21 namespace v8 { |
22 namespace internal { | 22 namespace internal { |
23 | 23 |
24 void PreParserTraits::ReportMessageAt(Scanner::Location location, | 24 void PreParserTraits::ReportMessageAt(Scanner::Location location, |
25 MessageTemplate::Template message, | 25 MessageTemplate::Template message, |
26 const char* arg, | 26 const char* arg, |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 // reported (underlining). | 674 // reported (underlining). |
675 Expect(Token::RETURN, CHECK_OK); | 675 Expect(Token::RETURN, CHECK_OK); |
676 function_state_->set_return_location(scanner()->location()); | 676 function_state_->set_return_location(scanner()->location()); |
677 | 677 |
678 // An ECMAScript program is considered syntactically incorrect if it | 678 // An ECMAScript program is considered syntactically incorrect if it |
679 // contains a return statement that is not within the body of a | 679 // contains a return statement that is not within the body of a |
680 // function. See ECMA-262, section 12.9, page 67. | 680 // function. See ECMA-262, section 12.9, page 67. |
681 // This is not handled during preparsing. | 681 // This is not handled during preparsing. |
682 | 682 |
683 Token::Value tok = peek(); | 683 Token::Value tok = peek(); |
| 684 int tail_call_position = -1; |
| 685 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) { |
| 686 Consume(Token::CONTINUE); |
| 687 tail_call_position = position(); |
| 688 tok = peek(); |
| 689 } |
684 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 690 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
685 tok != Token::SEMICOLON && | 691 tok != Token::SEMICOLON && |
686 tok != Token::RBRACE && | 692 tok != Token::RBRACE && |
687 tok != Token::EOS) { | 693 tok != Token::EOS) { |
688 ParseExpression(true, CHECK_OK); | 694 ParseExpression(true, CHECK_OK); |
| 695 if (tail_call_position >= 0) { |
| 696 if (!function_state_->collect_expressions_in_tail_position()) { |
| 697 Scanner::Location loc(tail_call_position, tail_call_position + 1); |
| 698 ReportMessageAt(loc, MessageTemplate::kTailCallInTryBlock); |
| 699 *ok = false; |
| 700 return Statement::Default(); |
| 701 } |
| 702 function_state_->AddExpressionInTailPosition( |
| 703 PreParserExpression::Default(), tail_call_position); |
| 704 } |
689 } | 705 } |
690 ExpectSemicolon(CHECK_OK); | 706 ExpectSemicolon(CHECK_OK); |
691 return Statement::Jump(); | 707 return Statement::Jump(); |
692 } | 708 } |
693 | 709 |
694 | 710 |
695 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { | 711 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
696 // WithStatement :: | 712 // WithStatement :: |
697 // 'with' '(' Expression ')' Statement | 713 // 'with' '(' Expression ')' Statement |
698 Expect(Token::WITH, CHECK_OK); | 714 Expect(Token::WITH, CHECK_OK); |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 // 'try' Block Catch Finally | 945 // 'try' Block Catch Finally |
930 // | 946 // |
931 // Catch :: | 947 // Catch :: |
932 // 'catch' '(' Identifier ')' Block | 948 // 'catch' '(' Identifier ')' Block |
933 // | 949 // |
934 // Finally :: | 950 // Finally :: |
935 // 'finally' Block | 951 // 'finally' Block |
936 | 952 |
937 Expect(Token::TRY, CHECK_OK); | 953 Expect(Token::TRY, CHECK_OK); |
938 | 954 |
939 ParseBlock(CHECK_OK); | 955 { |
| 956 DontCollectExpressionsInTailPositionScope no_tail_calls(function_state_); |
| 957 ParseBlock(CHECK_OK); |
| 958 } |
940 | 959 |
941 Token::Value tok = peek(); | 960 Token::Value tok = peek(); |
942 if (tok != Token::CATCH && tok != Token::FINALLY) { | 961 if (tok != Token::CATCH && tok != Token::FINALLY) { |
943 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); | 962 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); |
944 *ok = false; | 963 *ok = false; |
945 return Statement::Default(); | 964 return Statement::Default(); |
946 } | 965 } |
| 966 List<TailCallExpression> expressions_in_tail_position_in_catch_block; |
| 967 bool catch_block_exists = false; |
947 if (tok == Token::CATCH) { | 968 if (tok == Token::CATCH) { |
948 Consume(Token::CATCH); | 969 Consume(Token::CATCH); |
949 Expect(Token::LPAREN, CHECK_OK); | 970 Expect(Token::LPAREN, CHECK_OK); |
950 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); | 971 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); |
951 ExpressionClassifier pattern_classifier(this); | 972 ExpressionClassifier pattern_classifier(this); |
952 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 973 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
953 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 974 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
954 Expect(Token::RPAREN, CHECK_OK); | 975 Expect(Token::RPAREN, CHECK_OK); |
955 { | 976 { |
| 977 CollectExpressionsInTailPositionToListScope |
| 978 collect_expressions_in_tail_position_scope( |
| 979 function_state_, &expressions_in_tail_position_in_catch_block); |
956 BlockState block_state(&scope_, catch_scope); | 980 BlockState block_state(&scope_, catch_scope); |
957 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 981 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
958 { | 982 { |
959 BlockState block_state(&scope_, block_scope); | 983 BlockState block_state(&scope_, block_scope); |
960 ParseBlock(CHECK_OK); | 984 ParseBlock(CHECK_OK); |
961 } | 985 } |
962 } | 986 } |
| 987 catch_block_exists = true; |
963 tok = peek(); | 988 tok = peek(); |
964 } | 989 } |
965 if (tok == Token::FINALLY) { | 990 if (tok == Token::FINALLY) { |
966 Consume(Token::FINALLY); | 991 Consume(Token::FINALLY); |
967 ParseBlock(CHECK_OK); | 992 ParseBlock(CHECK_OK); |
| 993 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && |
| 994 expressions_in_tail_position_in_catch_block.length() > 0) { |
| 995 // TODO(ishell): update chapter number. |
| 996 // ES8 XX.YY.ZZ |
| 997 int pos = expressions_in_tail_position_in_catch_block[0].pos; |
| 998 ReportMessageAt(Scanner::Location(pos, pos + 1), |
| 999 MessageTemplate::kTailCallInCatchBlock); |
| 1000 *ok = false; |
| 1001 return Statement::Default(); |
| 1002 } |
968 } | 1003 } |
969 return Statement::Default(); | 1004 return Statement::Default(); |
970 } | 1005 } |
971 | 1006 |
972 | 1007 |
973 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { | 1008 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
974 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 1009 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
975 // contexts this is used as a statement which invokes the debugger as if a | 1010 // contexts this is used as a statement which invokes the debugger as if a |
976 // break point is present. | 1011 // break point is present. |
977 // DebuggerStatement :: | 1012 // DebuggerStatement :: |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 } | 1192 } |
1158 Expect(Token::RBRACE, CHECK_OK); | 1193 Expect(Token::RBRACE, CHECK_OK); |
1159 return PreParserExpression::Default(); | 1194 return PreParserExpression::Default(); |
1160 } | 1195 } |
1161 | 1196 |
1162 #undef CHECK_OK | 1197 #undef CHECK_OK |
1163 | 1198 |
1164 | 1199 |
1165 } // namespace internal | 1200 } // namespace internal |
1166 } // namespace v8 | 1201 } // namespace v8 |
OLD | NEW |