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 "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-expression-visitor.h" | 9 #include "src/ast/ast-expression-visitor.h" |
10 #include "src/ast/ast-literal-reindexer.h" | 10 #include "src/ast/ast-literal-reindexer.h" |
(...skipping 3308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3319 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); | 3319 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); |
3320 | 3320 |
3321 return factory()->NewBinaryOperation( | 3321 return factory()->NewBinaryOperation( |
3322 Token::AND, | 3322 Token::AND, |
3323 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), | 3323 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), |
3324 throw_call, pos); | 3324 throw_call, pos); |
3325 } | 3325 } |
3326 | 3326 |
3327 | 3327 |
3328 void Parser::InitializeForEachStatement(ForEachStatement* stmt, | 3328 void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
3329 Expression* each, | 3329 Expression* each, Expression* subject, |
3330 Expression* subject, | 3330 Statement* body, |
3331 Statement* body) { | 3331 bool is_destructuring) { |
3332 DCHECK(!is_destructuring || allow_harmony_destructuring_assignment()); | |
3332 ForOfStatement* for_of = stmt->AsForOfStatement(); | 3333 ForOfStatement* for_of = stmt->AsForOfStatement(); |
3333 | 3334 |
3334 if (for_of != NULL) { | 3335 if (for_of != NULL) { |
3335 Variable* iterator = scope_->NewTemporary( | 3336 Variable* iterator = scope_->NewTemporary( |
3336 ast_value_factory()->dot_iterator_string()); | 3337 ast_value_factory()->dot_iterator_string()); |
3337 Variable* result = scope_->NewTemporary( | 3338 Variable* result = scope_->NewTemporary( |
3338 ast_value_factory()->dot_result_string()); | 3339 ast_value_factory()->dot_result_string()); |
3339 | 3340 |
3340 Expression* assign_iterator; | 3341 Expression* assign_iterator; |
3341 Expression* next_result; | 3342 Expression* next_result; |
(...skipping 30 matching lines...) Expand all Loading... | |
3372 | 3373 |
3373 // each = result.value | 3374 // each = result.value |
3374 { | 3375 { |
3375 Expression* value_literal = factory()->NewStringLiteral( | 3376 Expression* value_literal = factory()->NewStringLiteral( |
3376 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | 3377 ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
3377 Expression* result_proxy = factory()->NewVariableProxy(result); | 3378 Expression* result_proxy = factory()->NewVariableProxy(result); |
3378 Expression* result_value = factory()->NewProperty( | 3379 Expression* result_value = factory()->NewProperty( |
3379 result_proxy, value_literal, RelocInfo::kNoPosition); | 3380 result_proxy, value_literal, RelocInfo::kNoPosition); |
3380 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | 3381 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, |
3381 RelocInfo::kNoPosition); | 3382 RelocInfo::kNoPosition); |
3383 if (is_destructuring) { | |
3384 assign_each = PatternRewriter::RewriteDestructuringAssignment( | |
3385 this, assign_each->AsAssignment(), scope_); | |
3386 } | |
3382 } | 3387 } |
3383 | 3388 |
3384 for_of->Initialize(each, subject, body, | 3389 for_of->Initialize(each, subject, body, |
3385 assign_iterator, | 3390 assign_iterator, |
3386 next_result, | 3391 next_result, |
3387 result_done, | 3392 result_done, |
3388 assign_each); | 3393 assign_each); |
3389 } else { | 3394 } else { |
3395 if (is_destructuring) { | |
3396 Variable* temp = | |
3397 scope_->NewTemporary(ast_value_factory()->empty_string()); | |
3398 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | |
3399 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( | |
3400 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, | |
3401 RelocInfo::kNoPosition), | |
3402 scope_); | |
3403 auto block = | |
3404 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); | |
3405 block->statements()->Add(factory()->NewExpressionStatement( | |
3406 assign_each, RelocInfo::kNoPosition), | |
3407 zone()); | |
3408 block->statements()->Add(body, zone()); | |
3409 body = block; | |
3410 each = factory()->NewVariableProxy(temp); | |
adamk
2015/12/10 22:44:17
It looks like each is always a VariableProxy in th
| |
3411 } | |
3390 stmt->Initialize(each, subject, body); | 3412 stmt->Initialize(each, subject, body); |
3391 } | 3413 } |
3392 } | 3414 } |
3393 | 3415 |
3394 | 3416 |
3395 Statement* Parser::DesugarLexicalBindingsInForStatement( | 3417 Statement* Parser::DesugarLexicalBindingsInForStatement( |
3396 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, | 3418 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, |
3397 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 3419 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
3398 Statement* body, bool* ok) { | 3420 Statement* body, bool* ok) { |
3399 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are | 3421 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3764 each_initialization_block, &descriptor, &decl, | 3786 each_initialization_block, &descriptor, &decl, |
3765 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings | 3787 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings |
3766 : nullptr, | 3788 : nullptr, |
3767 CHECK_OK); | 3789 CHECK_OK); |
3768 } | 3790 } |
3769 | 3791 |
3770 body_block->statements()->Add(each_initialization_block, zone()); | 3792 body_block->statements()->Add(each_initialization_block, zone()); |
3771 body_block->statements()->Add(body, zone()); | 3793 body_block->statements()->Add(body, zone()); |
3772 VariableProxy* temp_proxy = | 3794 VariableProxy* temp_proxy = |
3773 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | 3795 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
3774 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); | 3796 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, |
3797 false); | |
3775 scope_ = for_scope; | 3798 scope_ = for_scope; |
3776 body_scope->set_end_position(scanner()->location().end_pos); | 3799 body_scope->set_end_position(scanner()->location().end_pos); |
3777 body_scope = body_scope->FinalizeBlockScope(); | 3800 body_scope = body_scope->FinalizeBlockScope(); |
3778 if (body_scope != nullptr) { | 3801 if (body_scope != nullptr) { |
3779 body_block->set_scope(body_scope); | 3802 body_block->set_scope(body_scope); |
3780 } | 3803 } |
3781 | 3804 |
3782 // Create a TDZ for any lexically-bound names. | 3805 // Create a TDZ for any lexically-bound names. |
3783 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { | 3806 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { |
3784 DCHECK_NULL(init_block); | 3807 DCHECK_NULL(init_block); |
(...skipping 30 matching lines...) Expand all Loading... | |
3815 } | 3838 } |
3816 } else { | 3839 } else { |
3817 init = parsing_result.BuildInitializationBlock( | 3840 init = parsing_result.BuildInitializationBlock( |
3818 IsLexicalVariableMode(parsing_result.descriptor.mode) | 3841 IsLexicalVariableMode(parsing_result.descriptor.mode) |
3819 ? &lexical_bindings | 3842 ? &lexical_bindings |
3820 : nullptr, | 3843 : nullptr, |
3821 CHECK_OK); | 3844 CHECK_OK); |
3822 } | 3845 } |
3823 } else { | 3846 } else { |
3824 int lhs_beg_pos = peek_position(); | 3847 int lhs_beg_pos = peek_position(); |
3825 Expression* expression = ParseExpression(false, CHECK_OK); | 3848 ExpressionClassifier classifier; |
3849 Expression* expression = ParseExpression(false, &classifier, CHECK_OK); | |
3826 int lhs_end_pos = scanner()->location().end_pos; | 3850 int lhs_end_pos = scanner()->location().end_pos; |
3827 ForEachStatement::VisitMode mode; | 3851 ForEachStatement::VisitMode mode; |
3828 is_let_identifier_expression = | 3852 is_let_identifier_expression = |
3829 expression->IsVariableProxy() && | 3853 expression->IsVariableProxy() && |
3830 expression->AsVariableProxy()->raw_name() == | 3854 expression->AsVariableProxy()->raw_name() == |
3831 ast_value_factory()->let_string(); | 3855 ast_value_factory()->let_string(); |
3832 | 3856 |
3833 if (CheckInOrOf(&mode, ok)) { | 3857 if (CheckInOrOf(&mode, ok)) { |
3834 if (!*ok) return nullptr; | 3858 if (!*ok) return nullptr; |
3835 expression = this->CheckAndRewriteReferenceExpression( | 3859 bool is_destructuring = |
3836 expression, lhs_beg_pos, lhs_end_pos, | 3860 allow_harmony_destructuring_assignment() && |
3837 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); | 3861 (expression->IsArrayLiteral() || expression->IsObjectLiteral()); |
3862 if (is_destructuring) { | |
3863 ValidateAssignmentPattern(&classifier, CHECK_OK); | |
3864 } else { | |
3865 ValidateExpression(&classifier, CHECK_OK); | |
3866 expression = this->CheckAndRewriteReferenceExpression( | |
3867 expression, lhs_beg_pos, lhs_end_pos, | |
3868 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); | |
3869 } | |
3838 | 3870 |
3839 ForEachStatement* loop = | 3871 ForEachStatement* loop = |
3840 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3872 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3841 Target target(&this->target_stack_, loop); | 3873 Target target(&this->target_stack_, loop); |
3842 | 3874 |
3843 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3875 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3844 Expect(Token::RPAREN, CHECK_OK); | 3876 Expect(Token::RPAREN, CHECK_OK); |
3845 | 3877 |
3846 // Make a block around the statement in case a lexical binding | 3878 // Make a block around the statement in case a lexical binding |
3847 // is introduced, e.g. by a FunctionDeclaration. | 3879 // is introduced, e.g. by a FunctionDeclaration. |
3848 // This block must not use for_scope as its scope because if a | 3880 // This block must not use for_scope as its scope because if a |
3849 // lexical binding is introduced which overlaps with the for-in/of, | 3881 // lexical binding is introduced which overlaps with the for-in/of, |
3850 // expressions in head of the loop should actually have variables | 3882 // expressions in head of the loop should actually have variables |
3851 // resolved in the outer scope. | 3883 // resolved in the outer scope. |
3852 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); | 3884 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); |
3853 scope_ = body_scope; | 3885 scope_ = body_scope; |
3854 Block* block = | 3886 Block* block = |
3855 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 3887 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
3856 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3888 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3857 block->statements()->Add(body, zone()); | 3889 block->statements()->Add(body, zone()); |
3858 InitializeForEachStatement(loop, expression, enumerable, block); | 3890 InitializeForEachStatement(loop, expression, enumerable, block, |
3891 is_destructuring); | |
3859 scope_ = saved_scope; | 3892 scope_ = saved_scope; |
3860 body_scope->set_end_position(scanner()->location().end_pos); | 3893 body_scope->set_end_position(scanner()->location().end_pos); |
3861 body_scope = body_scope->FinalizeBlockScope(); | 3894 body_scope = body_scope->FinalizeBlockScope(); |
3862 if (body_scope != nullptr) { | 3895 if (body_scope != nullptr) { |
3863 block->set_scope(body_scope); | 3896 block->set_scope(body_scope); |
3864 } | 3897 } |
3865 for_scope->set_end_position(scanner()->location().end_pos); | 3898 for_scope->set_end_position(scanner()->location().end_pos); |
3866 for_scope = for_scope->FinalizeBlockScope(); | 3899 for_scope = for_scope->FinalizeBlockScope(); |
3867 DCHECK(for_scope == nullptr); | 3900 DCHECK(for_scope == nullptr); |
3868 // Parsed for-in loop. | 3901 // Parsed for-in loop. |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4548 : AstExpressionVisitor(stack_limit, root), | 4581 : AstExpressionVisitor(stack_limit, root), |
4549 parser_(parser), | 4582 parser_(parser), |
4550 scope_(scope) {} | 4583 scope_(scope) {} |
4551 | 4584 |
4552 private: | 4585 private: |
4553 void VisitExpression(Expression* expr) { | 4586 void VisitExpression(Expression* expr) { |
4554 RewritableAssignmentExpression* to_rewrite = | 4587 RewritableAssignmentExpression* to_rewrite = |
4555 expr->AsRewritableAssignmentExpression(); | 4588 expr->AsRewritableAssignmentExpression(); |
4556 if (to_rewrite == nullptr || to_rewrite->is_rewritten()) return; | 4589 if (to_rewrite == nullptr || to_rewrite->is_rewritten()) return; |
4557 | 4590 |
4558 bool ok = true; | |
4559 Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite, | 4591 Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite, |
4560 scope_, &ok); | 4592 scope_); |
4561 DCHECK(ok); | |
4562 } | 4593 } |
4563 | 4594 |
4564 private: | 4595 private: |
4565 Parser* parser_; | 4596 Parser* parser_; |
4566 Scope* scope_; | 4597 Scope* scope_; |
4567 }; | 4598 }; |
4568 | 4599 |
4569 | 4600 |
4570 void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) { | 4601 void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) { |
4571 InitializerRewriter rewriter(stack_limit_, expr, this, scope); | 4602 InitializerRewriter rewriter(stack_limit_, expr, this, scope); |
(...skipping 1951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6523 func->destructuring_assignments_to_rewrite(); | 6554 func->destructuring_assignments_to_rewrite(); |
6524 for (int i = assignments.length() - 1; i >= 0; --i) { | 6555 for (int i = assignments.length() - 1; i >= 0; --i) { |
6525 // Rewrite list in reverse, so that nested assignment patterns are rewritten | 6556 // Rewrite list in reverse, so that nested assignment patterns are rewritten |
6526 // correctly. | 6557 // correctly. |
6527 DestructuringAssignment pair = assignments.at(i); | 6558 DestructuringAssignment pair = assignments.at(i); |
6528 RewritableAssignmentExpression* to_rewrite = | 6559 RewritableAssignmentExpression* to_rewrite = |
6529 pair.assignment->AsRewritableAssignmentExpression(); | 6560 pair.assignment->AsRewritableAssignmentExpression(); |
6530 Scope* scope = pair.scope; | 6561 Scope* scope = pair.scope; |
6531 DCHECK_NOT_NULL(to_rewrite); | 6562 DCHECK_NOT_NULL(to_rewrite); |
6532 if (!to_rewrite->is_rewritten()) { | 6563 if (!to_rewrite->is_rewritten()) { |
6533 bool ok = true; | 6564 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); |
6534 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope, | |
6535 &ok); | |
6536 DCHECK(ok); | |
6537 } | 6565 } |
6538 } | 6566 } |
6539 } | 6567 } |
6540 | 6568 |
6541 | 6569 |
6542 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 6570 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
6543 DCHECK(expr->IsRewritableAssignmentExpression()); | 6571 DCHECK(expr->IsRewritableAssignmentExpression()); |
6544 parser_->function_state_->AddDestructuringAssignment( | 6572 parser_->function_state_->AddDestructuringAssignment( |
6545 Parser::DestructuringAssignment(expr, parser_->scope_)); | 6573 Parser::DestructuringAssignment(expr, parser_->scope_)); |
6546 } | 6574 } |
6547 | 6575 |
6548 | 6576 |
6549 } // namespace internal | 6577 } // namespace internal |
6550 } // namespace v8 | 6578 } // namespace v8 |
OLD | NEW |