Chromium Code Reviews| 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) { |
|
marja
2016/09/14 10:06:59
Wouldn't "DeclareCatchVariable" be a better name?
nickie
2016/09/14 10:19:09
It's not only declaring, it's also rewriting, intr
| |
| 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) { |
|
marja
2016/09/14 09:58:09
Would it be possible to push more of this work to
nickie
2016/09/14 10:08:15
I suppose it can, which will probably make this me
| |
| 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; | 1843 bool* ok) { |
| 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: | 1844 // Simplify the AST nodes by converting: |
| 1929 // 'try B0 catch B1 finally B2' | 1845 // 'try B0 catch B1 finally B2' |
| 1930 // to: | 1846 // to: |
| 1931 // 'try { try B0 catch B1 } finally B2' | 1847 // 'try { try B0 catch B1 } finally B2' |
| 1932 | 1848 |
| 1933 if (catch_block != NULL && finally_block != NULL) { | 1849 if (catch_block != nullptr && finally_block != nullptr) { |
| 1934 // If we have both, create an inner try/catch. | 1850 // If we have both, create an inner try/catch. |
| 1935 DCHECK(catch_scope != NULL && catch_variable != NULL); | 1851 DCHECK_NOT_NULL(catch_info.scope); |
| 1852 DCHECK_NOT_NULL(catch_info.variable); | |
| 1936 TryCatchStatement* statement; | 1853 TryCatchStatement* statement; |
| 1937 if (catch_for_promise_reject) { | 1854 if (catch_info.for_promise_reject) { |
| 1938 statement = factory()->NewTryCatchStatementForPromiseReject( | 1855 statement = factory()->NewTryCatchStatementForPromiseReject( |
| 1939 try_block, catch_scope, catch_variable, catch_block, | 1856 try_block, catch_info.scope, catch_info.variable, catch_block, |
| 1940 kNoSourcePosition); | 1857 kNoSourcePosition); |
| 1941 } else { | 1858 } else { |
| 1942 statement = factory()->NewTryCatchStatement(try_block, catch_scope, | 1859 statement = factory()->NewTryCatchStatement( |
| 1943 catch_variable, catch_block, | 1860 try_block, catch_info.scope, catch_info.variable, catch_block, |
| 1944 kNoSourcePosition); | 1861 kNoSourcePosition); |
| 1945 } | 1862 } |
| 1946 | 1863 |
| 1947 try_block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); | 1864 try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
| 1948 try_block->statements()->Add(statement, zone()); | 1865 try_block->statements()->Add(statement, zone()); |
| 1949 catch_block = NULL; // Clear to indicate it's been handled. | 1866 catch_block = nullptr; // Clear to indicate it's been handled. |
| 1950 } | 1867 } |
| 1951 | 1868 |
| 1952 TryStatement* result = NULL; | 1869 if (catch_block != nullptr) { |
| 1953 if (catch_block != NULL) { | |
| 1954 // For a try-catch construct append return expressions from the catch block | 1870 // For a try-catch construct append return expressions from the catch block |
| 1955 // to the list of return expressions. | 1871 // to the list of return expressions. |
| 1956 function_state_->tail_call_expressions().Append( | 1872 function_state_->tail_call_expressions().Append( |
| 1957 tail_call_expressions_in_catch_block); | 1873 catch_info.tail_call_expressions); |
| 1958 | 1874 |
| 1959 DCHECK(finally_block == NULL); | 1875 DCHECK_NULL(finally_block); |
| 1960 DCHECK(catch_scope != NULL && catch_variable != NULL); | 1876 DCHECK_NOT_NULL(catch_info.scope); |
| 1961 result = factory()->NewTryCatchStatement(try_block, catch_scope, | 1877 DCHECK_NOT_NULL(catch_info.variable); |
| 1962 catch_variable, catch_block, pos); | 1878 return factory()->NewTryCatchStatement( |
| 1879 try_block, catch_info.scope, catch_info.variable, catch_block, pos); | |
| 1880 } else if (FLAG_harmony_explicit_tailcalls && | |
| 1881 catch_info.tail_call_expressions.has_explicit_tail_calls()) { | |
| 1882 // TODO(ishell): update chapter number. | |
| 1883 // ES8 XX.YY.ZZ | |
| 1884 ReportMessageAt(catch_info.tail_call_expressions.location(), | |
| 1885 MessageTemplate::kUnexpectedTailCallInCatchBlock); | |
| 1886 *ok = false; | |
| 1887 return nullptr; | |
| 1963 } else { | 1888 } else { |
| 1964 if (FLAG_harmony_explicit_tailcalls && | 1889 DCHECK_NOT_NULL(finally_block); |
| 1965 tail_call_expressions_in_catch_block.has_explicit_tail_calls()) { | 1890 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 } | 1891 } |
| 1976 | |
| 1977 return result; | |
| 1978 } | 1892 } |
| 1979 | 1893 |
| 1980 | |
| 1981 // !%_IsJSReceiver(result = iterator.next()) && | 1894 // !%_IsJSReceiver(result = iterator.next()) && |
| 1982 // %ThrowIteratorResultNotAnObject(result) | 1895 // %ThrowIteratorResultNotAnObject(result) |
| 1983 Expression* Parser::BuildIteratorNextResult(Expression* iterator, | 1896 Expression* Parser::BuildIteratorNextResult(Expression* iterator, |
| 1984 Variable* result, int pos) { | 1897 Variable* result, int pos) { |
| 1985 Expression* next_literal = factory()->NewStringLiteral( | 1898 Expression* next_literal = factory()->NewStringLiteral( |
| 1986 ast_value_factory()->next_string(), kNoSourcePosition); | 1899 ast_value_factory()->next_string(), kNoSourcePosition); |
| 1987 Expression* next_property = | 1900 Expression* next_property = |
| 1988 factory()->NewProperty(iterator, next_literal, kNoSourcePosition); | 1901 factory()->NewProperty(iterator, next_literal, kNoSourcePosition); |
| 1989 ZoneList<Expression*>* next_arguments = | 1902 ZoneList<Expression*>* next_arguments = |
| 1990 new (zone()) ZoneList<Expression*>(0, zone()); | 1903 new (zone()) ZoneList<Expression*>(0, zone()); |
| (...skipping 3629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5620 node->Print(Isolate::Current()); | 5533 node->Print(Isolate::Current()); |
| 5621 } | 5534 } |
| 5622 #endif // DEBUG | 5535 #endif // DEBUG |
| 5623 | 5536 |
| 5624 #undef CHECK_OK | 5537 #undef CHECK_OK |
| 5625 #undef CHECK_OK_VOID | 5538 #undef CHECK_OK_VOID |
| 5626 #undef CHECK_FAILED | 5539 #undef CHECK_FAILED |
| 5627 | 5540 |
| 5628 } // namespace internal | 5541 } // namespace internal |
| 5629 } // namespace v8 | 5542 } // namespace v8 |
| OLD | NEW |