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 #ifndef V8_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
7 | 7 |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 | 282 |
283 class BlockState final : public ScopeState { | 283 class BlockState final : public ScopeState { |
284 public: | 284 public: |
285 BlockState(ScopeState** scope_stack, Scope* scope) | 285 BlockState(ScopeState** scope_stack, Scope* scope) |
286 : ScopeState(scope_stack, scope) {} | 286 : ScopeState(scope_stack, scope) {} |
287 | 287 |
288 // BlockState(ScopeState**) automatically manages Scope(BLOCK_SCOPE) | 288 // BlockState(ScopeState**) automatically manages Scope(BLOCK_SCOPE) |
289 // allocation. | 289 // allocation. |
290 // TODO(verwaest): Move to LazyBlockState class that only allocates the | 290 // TODO(verwaest): Move to LazyBlockState class that only allocates the |
291 // scope when needed. | 291 // scope when needed. |
292 explicit BlockState(ScopeState** scope_stack) | 292 explicit BlockState(Zone* zone, ScopeState** scope_stack) |
293 : ScopeState(scope_stack, NewScope(*scope_stack)) {} | 293 : ScopeState(scope_stack, NewScope(zone, *scope_stack)) {} |
294 | 294 |
295 void SetNonlinear() { this->scope()->SetNonlinear(); } | 295 void SetNonlinear() { this->scope()->SetNonlinear(); } |
296 void set_start_position(int pos) { this->scope()->set_start_position(pos); } | 296 void set_start_position(int pos) { this->scope()->set_start_position(pos); } |
297 void set_end_position(int pos) { this->scope()->set_end_position(pos); } | 297 void set_end_position(int pos) { this->scope()->set_end_position(pos); } |
298 void set_is_hidden() { this->scope()->set_is_hidden(); } | 298 void set_is_hidden() { this->scope()->set_is_hidden(); } |
299 Scope* FinalizedBlockScope() const { | 299 Scope* FinalizedBlockScope() const { |
300 return this->scope()->FinalizeBlockScope(); | 300 return this->scope()->FinalizeBlockScope(); |
301 } | 301 } |
302 LanguageMode language_mode() const { | 302 LanguageMode language_mode() const { |
303 return this->scope()->language_mode(); | 303 return this->scope()->language_mode(); |
304 } | 304 } |
305 | 305 |
306 private: | 306 private: |
307 Scope* NewScope(ScopeState* outer_state) { | 307 Scope* NewScope(Zone* zone, ScopeState* outer_state) { |
308 Scope* parent = outer_state->scope(); | 308 Scope* parent = outer_state->scope(); |
309 Zone* zone = outer_state->zone(); | |
310 return new (zone) Scope(zone, parent, BLOCK_SCOPE); | 309 return new (zone) Scope(zone, parent, BLOCK_SCOPE); |
311 } | 310 } |
312 }; | 311 }; |
313 | 312 |
314 struct DestructuringAssignment { | 313 struct DestructuringAssignment { |
315 public: | 314 public: |
316 DestructuringAssignment(ExpressionT expression, Scope* scope) | 315 DestructuringAssignment(ExpressionT expression, Scope* scope) |
317 : assignment(expression), scope(scope) {} | 316 : assignment(expression), scope(scope) {} |
318 | 317 |
319 ExpressionT assignment; | 318 ExpressionT assignment; |
(...skipping 3599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3919 formal_parameters.scope | 3918 formal_parameters.scope |
3920 ->AllowsLazyParsingWithoutUnresolvedVariables()); | 3919 ->AllowsLazyParsingWithoutUnresolvedVariables()); |
3921 // TODO(marja): consider lazy-parsing inner arrow functions too. is_this | 3920 // TODO(marja): consider lazy-parsing inner arrow functions too. is_this |
3922 // handling in Scope::ResolveVariable needs to change. | 3921 // handling in Scope::ResolveVariable needs to change. |
3923 if (is_lazily_parsed) { | 3922 if (is_lazily_parsed) { |
3924 Scanner::BookmarkScope bookmark(scanner()); | 3923 Scanner::BookmarkScope bookmark(scanner()); |
3925 bookmark.Set(); | 3924 bookmark.Set(); |
3926 LazyParsingResult result = impl()->SkipLazyFunctionBody( | 3925 LazyParsingResult result = impl()->SkipLazyFunctionBody( |
3927 &materialized_literal_count, &expected_property_count, false, true, | 3926 &materialized_literal_count, &expected_property_count, false, true, |
3928 CHECK_OK); | 3927 CHECK_OK); |
| 3928 formal_parameters.scope->ResetAfterPreparsing(result == |
| 3929 kLazyParsingAborted); |
3929 | 3930 |
3930 if (formal_parameters.materialized_literals_count > 0) { | 3931 if (formal_parameters.materialized_literals_count > 0) { |
3931 materialized_literal_count += | 3932 materialized_literal_count += |
3932 formal_parameters.materialized_literals_count; | 3933 formal_parameters.materialized_literals_count; |
3933 } | 3934 } |
3934 | 3935 |
3935 if (result == kLazyParsingAborted) { | 3936 if (result == kLazyParsingAborted) { |
3936 bookmark.Apply(); | 3937 bookmark.Apply(); |
3937 // Trigger eager (re-)parsing, just below this block. | 3938 // Trigger eager (re-)parsing, just below this block. |
3938 is_lazily_parsed = false; | 3939 is_lazily_parsed = false; |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4453 ZoneList<const AstRawString*>* labels, bool* ok) { | 4454 ZoneList<const AstRawString*>* labels, bool* ok) { |
4454 // Block :: | 4455 // Block :: |
4455 // '{' StatementList '}' | 4456 // '{' StatementList '}' |
4456 | 4457 |
4457 // Construct block expecting 16 statements. | 4458 // Construct block expecting 16 statements. |
4458 BlockT body = factory()->NewBlock(labels, 16, false, kNoSourcePosition); | 4459 BlockT body = factory()->NewBlock(labels, 16, false, kNoSourcePosition); |
4459 | 4460 |
4460 // Parse the statements and collect escaping labels. | 4461 // Parse the statements and collect escaping labels. |
4461 Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullBlock)); | 4462 Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullBlock)); |
4462 { | 4463 { |
4463 BlockState block_state(&scope_state_); | 4464 BlockState block_state(zone(), &scope_state_); |
4464 block_state.set_start_position(scanner()->location().beg_pos); | 4465 block_state.set_start_position(scanner()->location().beg_pos); |
4465 typename Types::Target target(this, body); | 4466 typename Types::Target target(this, body); |
4466 | 4467 |
4467 while (peek() != Token::RBRACE) { | 4468 while (peek() != Token::RBRACE) { |
4468 StatementT stat = ParseStatementListItem(CHECK_OK_CUSTOM(NullBlock)); | 4469 StatementT stat = ParseStatementListItem(CHECK_OK_CUSTOM(NullBlock)); |
4469 if (!impl()->IsNullStatement(stat) && !impl()->IsEmptyStatement(stat)) { | 4470 if (!impl()->IsNullStatement(stat) && !impl()->IsEmptyStatement(stat)) { |
4470 body->statements()->Add(stat, zone()); | 4471 body->statements()->Add(stat, zone()); |
4471 } | 4472 } |
4472 } | 4473 } |
4473 | 4474 |
4474 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); | 4475 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); |
4475 block_state.set_end_position(scanner()->location().end_pos); | 4476 block_state.set_end_position(scanner()->location().end_pos); |
4476 body->set_scope(block_state.FinalizedBlockScope()); | 4477 body->set_scope(block_state.FinalizedBlockScope()); |
4477 } | 4478 } |
4478 return body; | 4479 return body; |
4479 } | 4480 } |
4480 | 4481 |
4481 template <typename Impl> | 4482 template <typename Impl> |
4482 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement( | 4483 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement( |
4483 ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) { | 4484 ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) { |
4484 if (is_strict(language_mode()) || peek() != Token::FUNCTION || | 4485 if (is_strict(language_mode()) || peek() != Token::FUNCTION || |
4485 (legacy && allow_harmony_restrictive_declarations())) { | 4486 (legacy && allow_harmony_restrictive_declarations())) { |
4486 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); | 4487 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); |
4487 } else { | 4488 } else { |
4488 if (legacy) { | 4489 if (legacy) { |
4489 impl()->CountUsage(v8::Isolate::kLegacyFunctionDeclaration); | 4490 impl()->CountUsage(v8::Isolate::kLegacyFunctionDeclaration); |
4490 } | 4491 } |
4491 // Make a block around the statement for a lexical binding | 4492 // Make a block around the statement for a lexical binding |
4492 // is introduced by a FunctionDeclaration. | 4493 // is introduced by a FunctionDeclaration. |
4493 BlockState block_state(&scope_state_); | 4494 BlockState block_state(zone(), &scope_state_); |
4494 block_state.set_start_position(scanner()->location().beg_pos); | 4495 block_state.set_start_position(scanner()->location().beg_pos); |
4495 BlockT block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); | 4496 BlockT block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); |
4496 StatementT body = impl()->ParseFunctionDeclaration(CHECK_OK); | 4497 StatementT body = impl()->ParseFunctionDeclaration(CHECK_OK); |
4497 block->statements()->Add(body, zone()); | 4498 block->statements()->Add(body, zone()); |
4498 block_state.set_end_position(scanner()->location().end_pos); | 4499 block_state.set_end_position(scanner()->location().end_pos); |
4499 block->set_scope(block_state.FinalizedBlockScope()); | 4500 block->set_scope(block_state.FinalizedBlockScope()); |
4500 return block; | 4501 return block; |
4501 } | 4502 } |
4502 } | 4503 } |
4503 | 4504 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4854 int switch_pos = peek_position(); | 4855 int switch_pos = peek_position(); |
4855 | 4856 |
4856 Expect(Token::SWITCH, CHECK_OK); | 4857 Expect(Token::SWITCH, CHECK_OK); |
4857 Expect(Token::LPAREN, CHECK_OK); | 4858 Expect(Token::LPAREN, CHECK_OK); |
4858 ExpressionT tag = ParseExpression(true, CHECK_OK); | 4859 ExpressionT tag = ParseExpression(true, CHECK_OK); |
4859 Expect(Token::RPAREN, CHECK_OK); | 4860 Expect(Token::RPAREN, CHECK_OK); |
4860 | 4861 |
4861 auto switch_statement = factory()->NewSwitchStatement(labels, switch_pos); | 4862 auto switch_statement = factory()->NewSwitchStatement(labels, switch_pos); |
4862 | 4863 |
4863 { | 4864 { |
4864 BlockState cases_block_state(&scope_state_); | 4865 BlockState cases_block_state(zone(), &scope_state_); |
4865 cases_block_state.set_start_position(scanner()->location().beg_pos); | 4866 cases_block_state.set_start_position(scanner()->location().beg_pos); |
4866 cases_block_state.SetNonlinear(); | 4867 cases_block_state.SetNonlinear(); |
4867 typename Types::Target target(this, switch_statement); | 4868 typename Types::Target target(this, switch_statement); |
4868 | 4869 |
4869 bool default_seen = false; | 4870 bool default_seen = false; |
4870 auto cases = impl()->NewCaseClauseList(4); | 4871 auto cases = impl()->NewCaseClauseList(4); |
4871 Expect(Token::LBRACE, CHECK_OK); | 4872 Expect(Token::LBRACE, CHECK_OK); |
4872 while (peek() != Token::RBRACE) { | 4873 while (peek() != Token::RBRACE) { |
4873 // An empty label indicates the default case. | 4874 // An empty label indicates the default case. |
4874 ExpressionT label = impl()->EmptyExpression(); | 4875 ExpressionT label = impl()->EmptyExpression(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4945 CollectExpressionsInTailPositionToListScope | 4946 CollectExpressionsInTailPositionToListScope |
4946 collect_tail_call_expressions_scope( | 4947 collect_tail_call_expressions_scope( |
4947 function_state_, &catch_info.tail_call_expressions); | 4948 function_state_, &catch_info.tail_call_expressions); |
4948 BlockState catch_block_state(&scope_state_, catch_info.scope); | 4949 BlockState catch_block_state(&scope_state_, catch_info.scope); |
4949 | 4950 |
4950 catch_block = factory()->NewBlock(nullptr, 16, false, kNoSourcePosition); | 4951 catch_block = factory()->NewBlock(nullptr, 16, false, kNoSourcePosition); |
4951 | 4952 |
4952 // Create a block scope to hold any lexical declarations created | 4953 // Create a block scope to hold any lexical declarations created |
4953 // as part of destructuring the catch parameter. | 4954 // as part of destructuring the catch parameter. |
4954 { | 4955 { |
4955 BlockState catch_variable_block_state(&scope_state_); | 4956 BlockState catch_variable_block_state(zone(), &scope_state_); |
4956 catch_variable_block_state.set_start_position( | 4957 catch_variable_block_state.set_start_position( |
4957 scanner()->location().beg_pos); | 4958 scanner()->location().beg_pos); |
4958 typename Types::Target target(this, catch_block); | 4959 typename Types::Target target(this, catch_block); |
4959 | 4960 |
4960 // This does not simply call ParsePrimaryExpression to avoid | 4961 // This does not simply call ParsePrimaryExpression to avoid |
4961 // ExpressionFromIdentifier from being called in the first | 4962 // ExpressionFromIdentifier from being called in the first |
4962 // branch, which would introduce an unresolved symbol and mess | 4963 // branch, which would introduce an unresolved symbol and mess |
4963 // with arrow function names. | 4964 // with arrow function names. |
4964 if (peek_any_identifier()) { | 4965 if (peek_any_identifier()) { |
4965 catch_info.name = | 4966 catch_info.name = |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5010 } | 5011 } |
5011 | 5012 |
5012 template <typename Impl> | 5013 template <typename Impl> |
5013 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( | 5014 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( |
5014 ZoneList<const AstRawString*>* labels, bool* ok) { | 5015 ZoneList<const AstRawString*>* labels, bool* ok) { |
5015 int stmt_pos = peek_position(); | 5016 int stmt_pos = peek_position(); |
5016 ForInfo for_info(this); | 5017 ForInfo for_info(this); |
5017 bool bound_names_are_lexical = false; | 5018 bool bound_names_are_lexical = false; |
5018 | 5019 |
5019 // Create an in-between scope for let-bound iteration variables. | 5020 // Create an in-between scope for let-bound iteration variables. |
5020 BlockState for_state(&scope_state_); | 5021 BlockState for_state(zone(), &scope_state_); |
5021 Expect(Token::FOR, CHECK_OK); | 5022 Expect(Token::FOR, CHECK_OK); |
5022 Expect(Token::LPAREN, CHECK_OK); | 5023 Expect(Token::LPAREN, CHECK_OK); |
5023 for_state.set_start_position(scanner()->location().beg_pos); | 5024 for_state.set_start_position(scanner()->location().beg_pos); |
5024 for_state.set_is_hidden(); | 5025 for_state.set_is_hidden(); |
5025 | 5026 |
5026 StatementT init = impl()->NullStatement(); | 5027 StatementT init = impl()->NullStatement(); |
5027 if (peek() != Token::SEMICOLON) { | 5028 if (peek() != Token::SEMICOLON) { |
5028 // An initializer is present. | 5029 // An initializer is present. |
5029 if (peek() == Token::VAR || peek() == Token::CONST || | 5030 if (peek() == Token::VAR || peek() == Token::CONST || |
5030 (peek() == Token::LET && IsNextLetKeyword())) { | 5031 (peek() == Token::LET && IsNextLetKeyword())) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5081 } else { | 5082 } else { |
5082 enumerable = ParseExpression(true, CHECK_OK); | 5083 enumerable = ParseExpression(true, CHECK_OK); |
5083 } | 5084 } |
5084 | 5085 |
5085 Expect(Token::RPAREN, CHECK_OK); | 5086 Expect(Token::RPAREN, CHECK_OK); |
5086 | 5087 |
5087 StatementT final_loop = impl()->NullStatement(); | 5088 StatementT final_loop = impl()->NullStatement(); |
5088 { | 5089 { |
5089 ReturnExprScope no_tail_calls(function_state_, | 5090 ReturnExprScope no_tail_calls(function_state_, |
5090 ReturnExprContext::kInsideForInOfBody); | 5091 ReturnExprContext::kInsideForInOfBody); |
5091 BlockState block_state(&scope_state_); | 5092 BlockState block_state(zone(), &scope_state_); |
5092 block_state.set_start_position(scanner()->location().beg_pos); | 5093 block_state.set_start_position(scanner()->location().beg_pos); |
5093 | 5094 |
5094 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); | 5095 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
5095 | 5096 |
5096 BlockT body_block = impl()->NullBlock(); | 5097 BlockT body_block = impl()->NullBlock(); |
5097 ExpressionT each_variable = impl()->EmptyExpression(); | 5098 ExpressionT each_variable = impl()->EmptyExpression(); |
5098 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, | 5099 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, |
5099 &each_variable, CHECK_OK); | 5100 &each_variable, CHECK_OK); |
5100 body_block->statements()->Add(body, zone()); | 5101 body_block->statements()->Add(body, zone()); |
5101 final_loop = impl()->InitializeForEachStatement( | 5102 final_loop = impl()->InitializeForEachStatement( |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5164 impl()->RewriteNonPattern(CHECK_OK); | 5165 impl()->RewriteNonPattern(CHECK_OK); |
5165 } else { | 5166 } else { |
5166 enumerable = ParseExpression(true, CHECK_OK); | 5167 enumerable = ParseExpression(true, CHECK_OK); |
5167 } | 5168 } |
5168 | 5169 |
5169 Expect(Token::RPAREN, CHECK_OK); | 5170 Expect(Token::RPAREN, CHECK_OK); |
5170 | 5171 |
5171 { | 5172 { |
5172 ReturnExprScope no_tail_calls(function_state_, | 5173 ReturnExprScope no_tail_calls(function_state_, |
5173 ReturnExprContext::kInsideForInOfBody); | 5174 ReturnExprContext::kInsideForInOfBody); |
5174 BlockState block_state(&scope_state_); | 5175 BlockState block_state(zone(), &scope_state_); |
5175 block_state.set_start_position(scanner()->location().beg_pos); | 5176 block_state.set_start_position(scanner()->location().beg_pos); |
5176 | 5177 |
5177 // For legacy compat reasons, give for loops similar treatment to | 5178 // For legacy compat reasons, give for loops similar treatment to |
5178 // if statements in allowing a function declaration for a body | 5179 // if statements in allowing a function declaration for a body |
5179 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); | 5180 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
5180 block_state.set_end_position(scanner()->location().end_pos); | 5181 block_state.set_end_position(scanner()->location().end_pos); |
5181 StatementT final_loop = impl()->InitializeForEachStatement( | 5182 StatementT final_loop = impl()->InitializeForEachStatement( |
5182 loop, expression, enumerable, body, each_keyword_pos); | 5183 loop, expression, enumerable, body, each_keyword_pos); |
5183 | 5184 |
5184 Scope* for_scope = for_state.FinalizedBlockScope(); | 5185 Scope* for_scope = for_state.FinalizedBlockScope(); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5324 has_seen_constructor_ = true; | 5325 has_seen_constructor_ = true; |
5325 return; | 5326 return; |
5326 } | 5327 } |
5327 } | 5328 } |
5328 | 5329 |
5329 | 5330 |
5330 } // namespace internal | 5331 } // namespace internal |
5331 } // namespace v8 | 5332 } // namespace v8 |
5332 | 5333 |
5333 #endif // V8_PARSING_PARSER_BASE_H | 5334 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |