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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 1767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 | 1778 |
1779 Expression* tag_read = factory()->NewVariableProxy(tag_variable); | 1779 Expression* tag_read = factory()->NewVariableProxy(tag_variable); |
1780 switch_statement->Initialize(tag_read, cases); | 1780 switch_statement->Initialize(tag_read, cases); |
1781 Block* cases_block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); | 1781 Block* cases_block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); |
1782 cases_block->statements()->Add(switch_statement, zone()); | 1782 cases_block->statements()->Add(switch_statement, zone()); |
1783 cases_block->set_scope(scope); | 1783 cases_block->set_scope(scope); |
1784 switch_block->statements()->Add(cases_block, zone()); | 1784 switch_block->statements()->Add(cases_block, zone()); |
1785 return switch_block; | 1785 return switch_block; |
1786 } | 1786 } |
1787 | 1787 |
1788 TryStatement* Parser::ParseTryStatement(bool* ok) { | 1788 void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) { |
1789 // TryStatement :: | 1789 if (catch_info->name == nullptr) { |
1790 // 'try' Block Catch | 1790 DCHECK_NOT_NULL(catch_info->pattern); |
1791 // 'try' Block Finally | 1791 catch_info->name = ast_value_factory()->dot_catch_string(); |
1792 // 'try' Block Catch Finally | 1792 } |
1793 // | 1793 catch_info->variable = catch_info->scope->DeclareLocal( |
1794 // Catch :: | 1794 catch_info->name, VAR, kCreatedInitialized, NORMAL_VARIABLE); |
1795 // 'catch' '(' Identifier ')' Block | 1795 if (catch_info->pattern != nullptr) { |
1796 // | 1796 DeclarationDescriptor descriptor; |
1797 // Finally :: | 1797 descriptor.declaration_kind = DeclarationDescriptor::NORMAL; |
1798 // 'finally' Block | 1798 descriptor.scope = scope(); |
| 1799 descriptor.hoist_scope = nullptr; |
| 1800 descriptor.mode = LET; |
| 1801 descriptor.declaration_pos = catch_info->pattern->position(); |
| 1802 descriptor.initialization_pos = catch_info->pattern->position(); |
1799 | 1803 |
1800 Expect(Token::TRY, CHECK_OK); | 1804 // Initializer position for variables declared by the pattern. |
1801 int pos = position(); | 1805 const int initializer_position = position(); |
1802 | 1806 |
1803 Block* try_block; | 1807 DeclarationParsingResult::Declaration decl( |
1804 { | 1808 catch_info->pattern, initializer_position, |
1805 ReturnExprScope no_tail_calls(function_state_, | 1809 factory()->NewVariableProxy(catch_info->variable)); |
1806 ReturnExprContext::kInsideTryBlock); | 1810 |
1807 try_block = ParseBlock(NULL, CHECK_OK); | 1811 catch_info->init_block = |
| 1812 factory()->NewBlock(nullptr, 8, true, kNoSourcePosition); |
| 1813 PatternRewriter::DeclareAndInitializeVariables( |
| 1814 this, catch_info->init_block, &descriptor, &decl, |
| 1815 &catch_info->bound_names, ok); |
| 1816 } else { |
| 1817 catch_info->bound_names.Add(catch_info->name, zone()); |
1808 } | 1818 } |
| 1819 } |
1809 | 1820 |
1810 Token::Value tok = peek(); | 1821 void Parser::ValidateCatchBlock(const CatchInfo& catch_info, bool* ok) { |
| 1822 // Check for `catch(e) { let e; }` and similar errors. |
| 1823 Scope* inner_block_scope = catch_info.inner_block->scope(); |
| 1824 if (inner_block_scope != nullptr) { |
| 1825 Declaration* decl = inner_block_scope->CheckLexDeclarationsConflictingWith( |
| 1826 catch_info.bound_names); |
| 1827 if (decl != nullptr) { |
| 1828 const AstRawString* name = decl->proxy()->raw_name(); |
| 1829 int position = decl->proxy()->position(); |
| 1830 Scanner::Location location = |
| 1831 position == kNoSourcePosition |
| 1832 ? Scanner::Location::invalid() |
| 1833 : Scanner::Location(position, position + 1); |
| 1834 ReportMessageAt(location, MessageTemplate::kVarRedeclaration, name); |
| 1835 *ok = false; |
| 1836 } |
| 1837 } |
| 1838 } |
1811 | 1839 |
1812 bool catch_for_promise_reject = false; | 1840 Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block, |
1813 if (allow_natives() && tok == Token::MOD) { | 1841 Block* finally_block, |
1814 Consume(Token::MOD); | 1842 const CatchInfo& catch_info, int pos) { |
1815 catch_for_promise_reject = true; | |
1816 tok = peek(); | |
1817 } | |
1818 | |
1819 if (tok != Token::CATCH && tok != Token::FINALLY) { | |
1820 ReportMessage(MessageTemplate::kNoCatchOrFinally); | |
1821 *ok = false; | |
1822 return NULL; | |
1823 } | |
1824 | |
1825 Scope* catch_scope = NULL; | |
1826 Variable* catch_variable = NULL; | |
1827 Block* catch_block = NULL; | |
1828 TailCallExpressionList tail_call_expressions_in_catch_block(zone()); | |
1829 if (tok == Token::CATCH) { | |
1830 Consume(Token::CATCH); | |
1831 | |
1832 Expect(Token::LPAREN, CHECK_OK); | |
1833 catch_scope = NewScope(CATCH_SCOPE); | |
1834 catch_scope->set_start_position(scanner()->location().beg_pos); | |
1835 | |
1836 { | |
1837 CollectExpressionsInTailPositionToListScope | |
1838 collect_tail_call_expressions_scope( | |
1839 function_state_, &tail_call_expressions_in_catch_block); | |
1840 BlockState block_state(&scope_state_, catch_scope); | |
1841 | |
1842 catch_block = factory()->NewBlock(nullptr, 16, false, kNoSourcePosition); | |
1843 | |
1844 // Create a block scope to hold any lexical declarations created | |
1845 // as part of destructuring the catch parameter. | |
1846 { | |
1847 BlockState block_state(&scope_state_); | |
1848 block_state.set_start_position(scanner()->location().beg_pos); | |
1849 ParserTarget target(this, catch_block); | |
1850 | |
1851 const AstRawString* name = ast_value_factory()->dot_catch_string(); | |
1852 Expression* pattern = nullptr; | |
1853 if (peek_any_identifier()) { | |
1854 name = ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); | |
1855 } else { | |
1856 ExpressionClassifier pattern_classifier(this); | |
1857 pattern = ParsePrimaryExpression(CHECK_OK); | |
1858 ValidateBindingPattern(CHECK_OK); | |
1859 } | |
1860 catch_variable = catch_scope->DeclareLocal( | |
1861 name, VAR, kCreatedInitialized, NORMAL_VARIABLE); | |
1862 | |
1863 Expect(Token::RPAREN, CHECK_OK); | |
1864 | |
1865 ZoneList<const AstRawString*> bound_names(1, zone()); | |
1866 if (pattern != nullptr) { | |
1867 DeclarationDescriptor descriptor; | |
1868 descriptor.declaration_kind = DeclarationDescriptor::NORMAL; | |
1869 descriptor.scope = scope(); | |
1870 descriptor.hoist_scope = nullptr; | |
1871 descriptor.mode = LET; | |
1872 descriptor.declaration_pos = pattern->position(); | |
1873 descriptor.initialization_pos = pattern->position(); | |
1874 | |
1875 // Initializer position for variables declared by the pattern. | |
1876 const int initializer_position = position(); | |
1877 | |
1878 DeclarationParsingResult::Declaration decl( | |
1879 pattern, initializer_position, | |
1880 factory()->NewVariableProxy(catch_variable)); | |
1881 | |
1882 Block* init_block = | |
1883 factory()->NewBlock(nullptr, 8, true, kNoSourcePosition); | |
1884 PatternRewriter::DeclareAndInitializeVariables( | |
1885 this, init_block, &descriptor, &decl, &bound_names, CHECK_OK); | |
1886 catch_block->statements()->Add(init_block, zone()); | |
1887 } else { | |
1888 bound_names.Add(name, zone()); | |
1889 } | |
1890 | |
1891 Block* inner_block = ParseBlock(nullptr, CHECK_OK); | |
1892 catch_block->statements()->Add(inner_block, zone()); | |
1893 | |
1894 // Check for `catch(e) { let e; }` and similar errors. | |
1895 Scope* inner_block_scope = inner_block->scope(); | |
1896 if (inner_block_scope != nullptr) { | |
1897 Declaration* decl = | |
1898 inner_block_scope->CheckLexDeclarationsConflictingWith( | |
1899 bound_names); | |
1900 if (decl != nullptr) { | |
1901 const AstRawString* name = decl->proxy()->raw_name(); | |
1902 int position = decl->proxy()->position(); | |
1903 Scanner::Location location = | |
1904 position == kNoSourcePosition | |
1905 ? Scanner::Location::invalid() | |
1906 : Scanner::Location(position, position + 1); | |
1907 ReportMessageAt(location, MessageTemplate::kVarRedeclaration, name); | |
1908 *ok = false; | |
1909 return nullptr; | |
1910 } | |
1911 } | |
1912 block_state.set_end_position(scanner()->location().end_pos); | |
1913 catch_block->set_scope(block_state.FinalizedBlockScope()); | |
1914 } | |
1915 } | |
1916 | |
1917 catch_scope->set_end_position(scanner()->location().end_pos); | |
1918 tok = peek(); | |
1919 } | |
1920 | |
1921 Block* finally_block = NULL; | |
1922 DCHECK(tok == Token::FINALLY || catch_block != NULL); | |
1923 if (tok == Token::FINALLY) { | |
1924 Consume(Token::FINALLY); | |
1925 finally_block = ParseBlock(NULL, CHECK_OK); | |
1926 } | |
1927 | |
1928 // Simplify the AST nodes by converting: | 1843 // Simplify the AST nodes by converting: |
1929 // 'try B0 catch B1 finally B2' | 1844 // 'try B0 catch B1 finally B2' |
1930 // to: | 1845 // to: |
1931 // 'try { try B0 catch B1 } finally B2' | 1846 // 'try { try B0 catch B1 } finally B2' |
1932 | 1847 |
1933 if (catch_block != NULL && finally_block != NULL) { | 1848 if (catch_block != nullptr && finally_block != nullptr) { |
1934 // If we have both, create an inner try/catch. | 1849 // If we have both, create an inner try/catch. |
1935 DCHECK(catch_scope != NULL && catch_variable != NULL); | 1850 DCHECK_NOT_NULL(catch_info.scope); |
| 1851 DCHECK_NOT_NULL(catch_info.variable); |
1936 TryCatchStatement* statement; | 1852 TryCatchStatement* statement; |
1937 if (catch_for_promise_reject) { | 1853 if (catch_info.for_promise_reject) { |
1938 statement = factory()->NewTryCatchStatementForPromiseReject( | 1854 statement = factory()->NewTryCatchStatementForPromiseReject( |
1939 try_block, catch_scope, catch_variable, catch_block, | 1855 try_block, catch_info.scope, catch_info.variable, catch_block, |
1940 kNoSourcePosition); | 1856 kNoSourcePosition); |
1941 } else { | 1857 } else { |
1942 statement = factory()->NewTryCatchStatement(try_block, catch_scope, | 1858 statement = factory()->NewTryCatchStatement( |
1943 catch_variable, catch_block, | 1859 try_block, catch_info.scope, catch_info.variable, catch_block, |
1944 kNoSourcePosition); | 1860 kNoSourcePosition); |
1945 } | 1861 } |
1946 | 1862 |
1947 try_block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); | 1863 try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
1948 try_block->statements()->Add(statement, zone()); | 1864 try_block->statements()->Add(statement, zone()); |
1949 catch_block = NULL; // Clear to indicate it's been handled. | 1865 catch_block = nullptr; // Clear to indicate it's been handled. |
1950 } | 1866 } |
1951 | 1867 |
1952 TryStatement* result = NULL; | 1868 if (catch_block != nullptr) { |
1953 if (catch_block != NULL) { | |
1954 // For a try-catch construct append return expressions from the catch block | 1869 // For a try-catch construct append return expressions from the catch block |
1955 // to the list of return expressions. | 1870 // to the list of return expressions. |
1956 function_state_->tail_call_expressions().Append( | 1871 function_state_->tail_call_expressions().Append( |
1957 tail_call_expressions_in_catch_block); | 1872 catch_info.tail_call_expressions); |
1958 | 1873 |
1959 DCHECK(finally_block == NULL); | 1874 DCHECK_NULL(finally_block); |
1960 DCHECK(catch_scope != NULL && catch_variable != NULL); | 1875 DCHECK_NOT_NULL(catch_info.scope); |
1961 result = factory()->NewTryCatchStatement(try_block, catch_scope, | 1876 DCHECK_NOT_NULL(catch_info.variable); |
1962 catch_variable, catch_block, pos); | 1877 return factory()->NewTryCatchStatement( |
| 1878 try_block, catch_info.scope, catch_info.variable, catch_block, pos); |
1963 } else { | 1879 } else { |
1964 if (FLAG_harmony_explicit_tailcalls && | 1880 DCHECK_NOT_NULL(finally_block); |
1965 tail_call_expressions_in_catch_block.has_explicit_tail_calls()) { | 1881 return factory()->NewTryFinallyStatement(try_block, finally_block, pos); |
1966 // TODO(ishell): update chapter number. | |
1967 // ES8 XX.YY.ZZ | |
1968 ReportMessageAt(tail_call_expressions_in_catch_block.location(), | |
1969 MessageTemplate::kUnexpectedTailCallInCatchBlock); | |
1970 *ok = false; | |
1971 return NULL; | |
1972 } | |
1973 DCHECK(finally_block != NULL); | |
1974 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); | |
1975 } | 1882 } |
1976 | |
1977 return result; | |
1978 } | 1883 } |
1979 | 1884 |
1980 | |
1981 // !%_IsJSReceiver(result = iterator.next()) && | 1885 // !%_IsJSReceiver(result = iterator.next()) && |
1982 // %ThrowIteratorResultNotAnObject(result) | 1886 // %ThrowIteratorResultNotAnObject(result) |
1983 Expression* Parser::BuildIteratorNextResult(Expression* iterator, | 1887 Expression* Parser::BuildIteratorNextResult(Expression* iterator, |
1984 Variable* result, int pos) { | 1888 Variable* result, int pos) { |
1985 Expression* next_literal = factory()->NewStringLiteral( | 1889 Expression* next_literal = factory()->NewStringLiteral( |
1986 ast_value_factory()->next_string(), kNoSourcePosition); | 1890 ast_value_factory()->next_string(), kNoSourcePosition); |
1987 Expression* next_property = | 1891 Expression* next_property = |
1988 factory()->NewProperty(iterator, next_literal, kNoSourcePosition); | 1892 factory()->NewProperty(iterator, next_literal, kNoSourcePosition); |
1989 ZoneList<Expression*>* next_arguments = | 1893 ZoneList<Expression*>* next_arguments = |
1990 new (zone()) ZoneList<Expression*>(0, zone()); | 1894 new (zone()) ZoneList<Expression*>(0, zone()); |
(...skipping 3629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5620 node->Print(Isolate::Current()); | 5524 node->Print(Isolate::Current()); |
5621 } | 5525 } |
5622 #endif // DEBUG | 5526 #endif // DEBUG |
5623 | 5527 |
5624 #undef CHECK_OK | 5528 #undef CHECK_OK |
5625 #undef CHECK_OK_VOID | 5529 #undef CHECK_OK_VOID |
5626 #undef CHECK_FAILED | 5530 #undef CHECK_FAILED |
5627 | 5531 |
5628 } // namespace internal | 5532 } // namespace internal |
5629 } // namespace v8 | 5533 } // namespace v8 |
OLD | NEW |