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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 | 287 |
288 class BlockState final : public ScopeState { | 288 class BlockState final : public ScopeState { |
289 public: | 289 public: |
290 BlockState(ScopeState** scope_stack, Scope* scope) | 290 BlockState(ScopeState** scope_stack, Scope* scope) |
291 : ScopeState(scope_stack, scope) {} | 291 : ScopeState(scope_stack, scope) {} |
292 | 292 |
293 // BlockState(ScopeState**) automatically manages Scope(BLOCK_SCOPE) | 293 // BlockState(ScopeState**) automatically manages Scope(BLOCK_SCOPE) |
294 // allocation. | 294 // allocation. |
295 // TODO(verwaest): Move to LazyBlockState class that only allocates the | 295 // TODO(verwaest): Move to LazyBlockState class that only allocates the |
296 // scope when needed. | 296 // scope when needed. |
297 explicit BlockState(ScopeState** scope_stack) | 297 explicit BlockState(Zone* zone, ScopeState** scope_stack) |
298 : ScopeState(scope_stack, NewScope(*scope_stack)) {} | 298 : ScopeState(scope_stack, NewScope(zone, *scope_stack)) {} |
299 | 299 |
300 void SetNonlinear() { this->scope()->SetNonlinear(); } | 300 void SetNonlinear() { this->scope()->SetNonlinear(); } |
301 void set_start_position(int pos) { this->scope()->set_start_position(pos); } | 301 void set_start_position(int pos) { this->scope()->set_start_position(pos); } |
302 void set_end_position(int pos) { this->scope()->set_end_position(pos); } | 302 void set_end_position(int pos) { this->scope()->set_end_position(pos); } |
303 void set_is_hidden() { this->scope()->set_is_hidden(); } | 303 void set_is_hidden() { this->scope()->set_is_hidden(); } |
304 Scope* FinalizedBlockScope() const { | 304 Scope* FinalizedBlockScope() const { |
305 return this->scope()->FinalizeBlockScope(); | 305 return this->scope()->FinalizeBlockScope(); |
306 } | 306 } |
307 LanguageMode language_mode() const { | 307 LanguageMode language_mode() const { |
308 return this->scope()->language_mode(); | 308 return this->scope()->language_mode(); |
309 } | 309 } |
310 | 310 |
311 private: | 311 private: |
312 Scope* NewScope(ScopeState* outer_state) { | 312 Scope* NewScope(Zone* zone, ScopeState* outer_state) { |
313 Scope* parent = outer_state->scope(); | 313 Scope* parent = outer_state->scope(); |
314 Zone* zone = outer_state->zone(); | |
315 return new (zone) Scope(zone, parent, BLOCK_SCOPE); | 314 return new (zone) Scope(zone, parent, BLOCK_SCOPE); |
316 } | 315 } |
317 }; | 316 }; |
318 | 317 |
319 struct DestructuringAssignment { | 318 struct DestructuringAssignment { |
320 public: | 319 public: |
321 DestructuringAssignment(ExpressionT expression, Scope* scope) | 320 DestructuringAssignment(ExpressionT expression, Scope* scope) |
322 : assignment(expression), scope(scope) {} | 321 : assignment(expression), scope(scope) {} |
323 | 322 |
324 ExpressionT assignment; | 323 ExpressionT assignment; |
(...skipping 3509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3834 formal_parameters.scope | 3833 formal_parameters.scope |
3835 ->AllowsLazyParsingWithoutUnresolvedVariables()); | 3834 ->AllowsLazyParsingWithoutUnresolvedVariables()); |
3836 // TODO(marja): consider lazy-parsing inner arrow functions too. is_this | 3835 // TODO(marja): consider lazy-parsing inner arrow functions too. is_this |
3837 // handling in Scope::ResolveVariable needs to change. | 3836 // handling in Scope::ResolveVariable needs to change. |
3838 if (is_lazily_parsed) { | 3837 if (is_lazily_parsed) { |
3839 Scanner::BookmarkScope bookmark(scanner()); | 3838 Scanner::BookmarkScope bookmark(scanner()); |
3840 bookmark.Set(); | 3839 bookmark.Set(); |
3841 LazyParsingResult result = impl()->SkipLazyFunctionBody( | 3840 LazyParsingResult result = impl()->SkipLazyFunctionBody( |
3842 &materialized_literal_count, &expected_property_count, false, true, | 3841 &materialized_literal_count, &expected_property_count, false, true, |
3843 CHECK_OK); | 3842 CHECK_OK); |
| 3843 formal_parameters.scope->ResetAfterPreparsing(result == |
| 3844 kLazyParsingAborted); |
3844 | 3845 |
3845 if (formal_parameters.materialized_literals_count > 0) { | 3846 if (formal_parameters.materialized_literals_count > 0) { |
3846 materialized_literal_count += | 3847 materialized_literal_count += |
3847 formal_parameters.materialized_literals_count; | 3848 formal_parameters.materialized_literals_count; |
3848 } | 3849 } |
3849 | 3850 |
3850 if (result == kLazyParsingAborted) { | 3851 if (result == kLazyParsingAborted) { |
3851 bookmark.Apply(); | 3852 bookmark.Apply(); |
3852 // Trigger eager (re-)parsing, just below this block. | 3853 // Trigger eager (re-)parsing, just below this block. |
3853 is_lazily_parsed = false; | 3854 is_lazily_parsed = false; |
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4423 ZoneList<const AstRawString*>* labels, bool* ok) { | 4424 ZoneList<const AstRawString*>* labels, bool* ok) { |
4424 // Block :: | 4425 // Block :: |
4425 // '{' StatementList '}' | 4426 // '{' StatementList '}' |
4426 | 4427 |
4427 // Construct block expecting 16 statements. | 4428 // Construct block expecting 16 statements. |
4428 BlockT body = factory()->NewBlock(labels, 16, false, kNoSourcePosition); | 4429 BlockT body = factory()->NewBlock(labels, 16, false, kNoSourcePosition); |
4429 | 4430 |
4430 // Parse the statements and collect escaping labels. | 4431 // Parse the statements and collect escaping labels. |
4431 Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullBlock)); | 4432 Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullBlock)); |
4432 { | 4433 { |
4433 BlockState block_state(&scope_state_); | 4434 BlockState block_state(zone(), &scope_state_); |
4434 block_state.set_start_position(scanner()->location().beg_pos); | 4435 block_state.set_start_position(scanner()->location().beg_pos); |
4435 typename Types::Target target(this, body); | 4436 typename Types::Target target(this, body); |
4436 | 4437 |
4437 while (peek() != Token::RBRACE) { | 4438 while (peek() != Token::RBRACE) { |
4438 StatementT stat = ParseStatementListItem(CHECK_OK_CUSTOM(NullBlock)); | 4439 StatementT stat = ParseStatementListItem(CHECK_OK_CUSTOM(NullBlock)); |
4439 if (!impl()->IsNullStatement(stat) && !impl()->IsEmptyStatement(stat)) { | 4440 if (!impl()->IsNullStatement(stat) && !impl()->IsEmptyStatement(stat)) { |
4440 body->statements()->Add(stat, zone()); | 4441 body->statements()->Add(stat, zone()); |
4441 } | 4442 } |
4442 } | 4443 } |
4443 | 4444 |
4444 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); | 4445 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); |
4445 block_state.set_end_position(scanner()->location().end_pos); | 4446 block_state.set_end_position(scanner()->location().end_pos); |
4446 body->set_scope(block_state.FinalizedBlockScope()); | 4447 body->set_scope(block_state.FinalizedBlockScope()); |
4447 } | 4448 } |
4448 return body; | 4449 return body; |
4449 } | 4450 } |
4450 | 4451 |
4451 template <typename Impl> | 4452 template <typename Impl> |
4452 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement( | 4453 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement( |
4453 ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) { | 4454 ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) { |
4454 if (is_strict(language_mode()) || peek() != Token::FUNCTION || | 4455 if (is_strict(language_mode()) || peek() != Token::FUNCTION || |
4455 (legacy && allow_harmony_restrictive_declarations())) { | 4456 (legacy && allow_harmony_restrictive_declarations())) { |
4456 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); | 4457 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); |
4457 } else { | 4458 } else { |
4458 if (legacy) { | 4459 if (legacy) { |
4459 impl()->CountUsage(v8::Isolate::kLegacyFunctionDeclaration); | 4460 impl()->CountUsage(v8::Isolate::kLegacyFunctionDeclaration); |
4460 } | 4461 } |
4461 // Make a block around the statement for a lexical binding | 4462 // Make a block around the statement for a lexical binding |
4462 // is introduced by a FunctionDeclaration. | 4463 // is introduced by a FunctionDeclaration. |
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 BlockT block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); | 4466 BlockT block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); |
4466 StatementT body = impl()->ParseFunctionDeclaration(CHECK_OK); | 4467 StatementT body = impl()->ParseFunctionDeclaration(CHECK_OK); |
4467 block->statements()->Add(body, zone()); | 4468 block->statements()->Add(body, zone()); |
4468 block_state.set_end_position(scanner()->location().end_pos); | 4469 block_state.set_end_position(scanner()->location().end_pos); |
4469 block->set_scope(block_state.FinalizedBlockScope()); | 4470 block->set_scope(block_state.FinalizedBlockScope()); |
4470 return block; | 4471 return block; |
4471 } | 4472 } |
4472 } | 4473 } |
4473 | 4474 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4824 int switch_pos = peek_position(); | 4825 int switch_pos = peek_position(); |
4825 | 4826 |
4826 Expect(Token::SWITCH, CHECK_OK); | 4827 Expect(Token::SWITCH, CHECK_OK); |
4827 Expect(Token::LPAREN, CHECK_OK); | 4828 Expect(Token::LPAREN, CHECK_OK); |
4828 ExpressionT tag = ParseExpression(true, CHECK_OK); | 4829 ExpressionT tag = ParseExpression(true, CHECK_OK); |
4829 Expect(Token::RPAREN, CHECK_OK); | 4830 Expect(Token::RPAREN, CHECK_OK); |
4830 | 4831 |
4831 auto switch_statement = factory()->NewSwitchStatement(labels, switch_pos); | 4832 auto switch_statement = factory()->NewSwitchStatement(labels, switch_pos); |
4832 | 4833 |
4833 { | 4834 { |
4834 BlockState cases_block_state(&scope_state_); | 4835 BlockState cases_block_state(zone(), &scope_state_); |
4835 cases_block_state.set_start_position(scanner()->location().beg_pos); | 4836 cases_block_state.set_start_position(scanner()->location().beg_pos); |
4836 cases_block_state.SetNonlinear(); | 4837 cases_block_state.SetNonlinear(); |
4837 typename Types::Target target(this, switch_statement); | 4838 typename Types::Target target(this, switch_statement); |
4838 | 4839 |
4839 bool default_seen = false; | 4840 bool default_seen = false; |
4840 auto cases = impl()->NewCaseClauseList(4); | 4841 auto cases = impl()->NewCaseClauseList(4); |
4841 Expect(Token::LBRACE, CHECK_OK); | 4842 Expect(Token::LBRACE, CHECK_OK); |
4842 while (peek() != Token::RBRACE) { | 4843 while (peek() != Token::RBRACE) { |
4843 // An empty label indicates the default case. | 4844 // An empty label indicates the default case. |
4844 ExpressionT label = impl()->EmptyExpression(); | 4845 ExpressionT label = impl()->EmptyExpression(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4915 CollectExpressionsInTailPositionToListScope | 4916 CollectExpressionsInTailPositionToListScope |
4916 collect_tail_call_expressions_scope( | 4917 collect_tail_call_expressions_scope( |
4917 function_state_, &catch_info.tail_call_expressions); | 4918 function_state_, &catch_info.tail_call_expressions); |
4918 BlockState catch_block_state(&scope_state_, catch_info.scope); | 4919 BlockState catch_block_state(&scope_state_, catch_info.scope); |
4919 | 4920 |
4920 catch_block = factory()->NewBlock(nullptr, 16, false, kNoSourcePosition); | 4921 catch_block = factory()->NewBlock(nullptr, 16, false, kNoSourcePosition); |
4921 | 4922 |
4922 // Create a block scope to hold any lexical declarations created | 4923 // Create a block scope to hold any lexical declarations created |
4923 // as part of destructuring the catch parameter. | 4924 // as part of destructuring the catch parameter. |
4924 { | 4925 { |
4925 BlockState catch_variable_block_state(&scope_state_); | 4926 BlockState catch_variable_block_state(zone(), &scope_state_); |
4926 catch_variable_block_state.set_start_position( | 4927 catch_variable_block_state.set_start_position( |
4927 scanner()->location().beg_pos); | 4928 scanner()->location().beg_pos); |
4928 typename Types::Target target(this, catch_block); | 4929 typename Types::Target target(this, catch_block); |
4929 | 4930 |
4930 // This does not simply call ParsePrimaryExpression to avoid | 4931 // This does not simply call ParsePrimaryExpression to avoid |
4931 // ExpressionFromIdentifier from being called in the first | 4932 // ExpressionFromIdentifier from being called in the first |
4932 // branch, which would introduce an unresolved symbol and mess | 4933 // branch, which would introduce an unresolved symbol and mess |
4933 // with arrow function names. | 4934 // with arrow function names. |
4934 if (peek_any_identifier()) { | 4935 if (peek_any_identifier()) { |
4935 catch_info.name = | 4936 catch_info.name = |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4970 } | 4971 } |
4971 | 4972 |
4972 template <typename Impl> | 4973 template <typename Impl> |
4973 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( | 4974 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( |
4974 ZoneList<const AstRawString*>* labels, bool* ok) { | 4975 ZoneList<const AstRawString*>* labels, bool* ok) { |
4975 int stmt_pos = peek_position(); | 4976 int stmt_pos = peek_position(); |
4976 ForInfo for_info(this); | 4977 ForInfo for_info(this); |
4977 bool bound_names_are_lexical = false; | 4978 bool bound_names_are_lexical = false; |
4978 | 4979 |
4979 // Create an in-between scope for let-bound iteration variables. | 4980 // Create an in-between scope for let-bound iteration variables. |
4980 BlockState for_state(&scope_state_); | 4981 BlockState for_state(zone(), &scope_state_); |
4981 Expect(Token::FOR, CHECK_OK); | 4982 Expect(Token::FOR, CHECK_OK); |
4982 Expect(Token::LPAREN, CHECK_OK); | 4983 Expect(Token::LPAREN, CHECK_OK); |
4983 for_state.set_start_position(scanner()->location().beg_pos); | 4984 for_state.set_start_position(scanner()->location().beg_pos); |
4984 for_state.set_is_hidden(); | 4985 for_state.set_is_hidden(); |
4985 | 4986 |
4986 StatementT init = impl()->NullStatement(); | 4987 StatementT init = impl()->NullStatement(); |
4987 if (peek() != Token::SEMICOLON) { | 4988 if (peek() != Token::SEMICOLON) { |
4988 // An initializer is present. | 4989 // An initializer is present. |
4989 if (peek() == Token::VAR || peek() == Token::CONST || | 4990 if (peek() == Token::VAR || peek() == Token::CONST || |
4990 (peek() == Token::LET && IsNextLetKeyword())) { | 4991 (peek() == Token::LET && IsNextLetKeyword())) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5041 } else { | 5042 } else { |
5042 enumerable = ParseExpression(true, CHECK_OK); | 5043 enumerable = ParseExpression(true, CHECK_OK); |
5043 } | 5044 } |
5044 | 5045 |
5045 Expect(Token::RPAREN, CHECK_OK); | 5046 Expect(Token::RPAREN, CHECK_OK); |
5046 | 5047 |
5047 StatementT final_loop = impl()->NullStatement(); | 5048 StatementT final_loop = impl()->NullStatement(); |
5048 { | 5049 { |
5049 ReturnExprScope no_tail_calls(function_state_, | 5050 ReturnExprScope no_tail_calls(function_state_, |
5050 ReturnExprContext::kInsideForInOfBody); | 5051 ReturnExprContext::kInsideForInOfBody); |
5051 BlockState block_state(&scope_state_); | 5052 BlockState block_state(zone(), &scope_state_); |
5052 block_state.set_start_position(scanner()->location().beg_pos); | 5053 block_state.set_start_position(scanner()->location().beg_pos); |
5053 | 5054 |
5054 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); | 5055 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
5055 | 5056 |
5056 BlockT body_block = impl()->NullBlock(); | 5057 BlockT body_block = impl()->NullBlock(); |
5057 ExpressionT each_variable = impl()->EmptyExpression(); | 5058 ExpressionT each_variable = impl()->EmptyExpression(); |
5058 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, | 5059 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, |
5059 &each_variable, CHECK_OK); | 5060 &each_variable, CHECK_OK); |
5060 body_block->statements()->Add(body, zone()); | 5061 body_block->statements()->Add(body, zone()); |
5061 final_loop = impl()->InitializeForEachStatement( | 5062 final_loop = impl()->InitializeForEachStatement( |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5124 impl()->RewriteNonPattern(CHECK_OK); | 5125 impl()->RewriteNonPattern(CHECK_OK); |
5125 } else { | 5126 } else { |
5126 enumerable = ParseExpression(true, CHECK_OK); | 5127 enumerable = ParseExpression(true, CHECK_OK); |
5127 } | 5128 } |
5128 | 5129 |
5129 Expect(Token::RPAREN, CHECK_OK); | 5130 Expect(Token::RPAREN, CHECK_OK); |
5130 | 5131 |
5131 { | 5132 { |
5132 ReturnExprScope no_tail_calls(function_state_, | 5133 ReturnExprScope no_tail_calls(function_state_, |
5133 ReturnExprContext::kInsideForInOfBody); | 5134 ReturnExprContext::kInsideForInOfBody); |
5134 BlockState block_state(&scope_state_); | 5135 BlockState block_state(zone(), &scope_state_); |
5135 block_state.set_start_position(scanner()->location().beg_pos); | 5136 block_state.set_start_position(scanner()->location().beg_pos); |
5136 | 5137 |
5137 // For legacy compat reasons, give for loops similar treatment to | 5138 // For legacy compat reasons, give for loops similar treatment to |
5138 // if statements in allowing a function declaration for a body | 5139 // if statements in allowing a function declaration for a body |
5139 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); | 5140 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
5140 block_state.set_end_position(scanner()->location().end_pos); | 5141 block_state.set_end_position(scanner()->location().end_pos); |
5141 StatementT final_loop = impl()->InitializeForEachStatement( | 5142 StatementT final_loop = impl()->InitializeForEachStatement( |
5142 loop, expression, enumerable, body, each_keyword_pos); | 5143 loop, expression, enumerable, body, each_keyword_pos); |
5143 | 5144 |
5144 Scope* for_scope = for_state.FinalizedBlockScope(); | 5145 Scope* for_scope = for_state.FinalizedBlockScope(); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5284 has_seen_constructor_ = true; | 5285 has_seen_constructor_ = true; |
5285 return; | 5286 return; |
5286 } | 5287 } |
5287 } | 5288 } |
5288 | 5289 |
5289 | 5290 |
5290 } // namespace internal | 5291 } // namespace internal |
5291 } // namespace v8 | 5292 } // namespace v8 |
5292 | 5293 |
5293 #endif // V8_PARSING_PARSER_BASE_H | 5294 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |