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-rewriter.h" | 9 #include "src/ast/ast-expression-rewriter.h" |
10 #include "src/ast/ast-expression-visitor.h" | 10 #include "src/ast/ast-expression-visitor.h" |
(...skipping 3232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3243 throw_arguments->Add(result_proxy_again, zone()); | 3243 throw_arguments->Add(result_proxy_again, zone()); |
3244 Expression* throw_call = factory()->NewCallRuntime( | 3244 Expression* throw_call = factory()->NewCallRuntime( |
3245 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); | 3245 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); |
3246 | 3246 |
3247 return factory()->NewBinaryOperation( | 3247 return factory()->NewBinaryOperation( |
3248 Token::AND, | 3248 Token::AND, |
3249 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), | 3249 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), |
3250 throw_call, pos); | 3250 throw_call, pos); |
3251 } | 3251 } |
3252 | 3252 |
3253 | |
3254 void Parser::InitializeForEachStatement(ForEachStatement* stmt, | 3253 void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
3255 Expression* each, Expression* subject, | 3254 Expression* each, Expression* subject, |
3256 Statement* body, | 3255 Statement* body) { |
3257 bool is_destructuring) { | |
3258 DCHECK(!is_destructuring || allow_harmony_destructuring_assignment()); | |
3259 ForOfStatement* for_of = stmt->AsForOfStatement(); | 3256 ForOfStatement* for_of = stmt->AsForOfStatement(); |
3260 | |
3261 if (for_of != NULL) { | 3257 if (for_of != NULL) { |
3262 Variable* iterator = scope_->NewTemporary( | 3258 InitializeForOfStatement(for_of, each, subject, body, |
3263 ast_value_factory()->dot_iterator_string()); | 3259 RelocInfo::kNoPosition); |
3264 Variable* result = scope_->NewTemporary( | |
3265 ast_value_factory()->dot_result_string()); | |
3266 | |
3267 Expression* assign_iterator; | |
3268 Expression* next_result; | |
3269 Expression* result_done; | |
3270 Expression* assign_each; | |
3271 | |
3272 // iterator = subject[Symbol.iterator]() | |
3273 // Hackily disambiguate o from o.next and o [Symbol.iterator](). | |
3274 // TODO(verwaest): Come up with a better solution. | |
3275 assign_iterator = factory()->NewAssignment( | |
3276 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
3277 GetIterator(subject, factory(), subject->position() - 2), | |
3278 subject->position()); | |
3279 | |
3280 // !%_IsJSReceiver(result = iterator.next()) && | |
3281 // %ThrowIteratorResultNotAnObject(result) | |
3282 { | |
3283 // result = iterator.next() | |
3284 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
3285 // Hackily disambiguate o from o.next and o [Symbol.iterator](). | |
3286 // TODO(verwaest): Come up with a better solution. | |
3287 next_result = BuildIteratorNextResult(iterator_proxy, result, | |
3288 subject->position() - 1); | |
3289 } | |
3290 | |
3291 // result.done | |
3292 { | |
3293 Expression* done_literal = factory()->NewStringLiteral( | |
3294 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
3295 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3296 result_done = factory()->NewProperty( | |
3297 result_proxy, done_literal, RelocInfo::kNoPosition); | |
3298 } | |
3299 | |
3300 // each = result.value | |
3301 { | |
3302 Expression* value_literal = factory()->NewStringLiteral( | |
3303 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
3304 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3305 Expression* result_value = factory()->NewProperty( | |
3306 result_proxy, value_literal, RelocInfo::kNoPosition); | |
3307 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | |
3308 RelocInfo::kNoPosition); | |
3309 if (is_destructuring) { | |
3310 assign_each = PatternRewriter::RewriteDestructuringAssignment( | |
3311 this, assign_each->AsAssignment(), scope_); | |
3312 } | |
3313 } | |
3314 | |
3315 for_of->Initialize(each, subject, body, | |
3316 iterator, | |
3317 assign_iterator, | |
3318 next_result, | |
3319 result_done, | |
3320 assign_each); | |
3321 } else { | 3260 } else { |
3322 if (is_destructuring) { | 3261 if (each->IsArrayLiteral() || each->IsObjectLiteral()) { |
| 3262 DCHECK(allow_harmony_destructuring_assignment()); |
3323 Variable* temp = | 3263 Variable* temp = |
3324 scope_->NewTemporary(ast_value_factory()->empty_string()); | 3264 scope_->NewTemporary(ast_value_factory()->empty_string()); |
3325 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3265 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
3326 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( | 3266 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( |
3327 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, | 3267 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, |
3328 RelocInfo::kNoPosition), | 3268 RelocInfo::kNoPosition), |
3329 scope_); | 3269 scope_); |
3330 auto block = | 3270 auto block = |
3331 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); | 3271 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); |
3332 block->statements()->Add(factory()->NewExpressionStatement( | 3272 block->statements()->Add(factory()->NewExpressionStatement( |
3333 assign_each, RelocInfo::kNoPosition), | 3273 assign_each, RelocInfo::kNoPosition), |
3334 zone()); | 3274 zone()); |
3335 block->statements()->Add(body, zone()); | 3275 block->statements()->Add(body, zone()); |
3336 body = block; | 3276 body = block; |
3337 each = factory()->NewVariableProxy(temp); | 3277 each = factory()->NewVariableProxy(temp); |
3338 } | 3278 } |
3339 stmt->Initialize(each, subject, body); | 3279 stmt->Initialize(each, subject, body); |
3340 } | 3280 } |
3341 } | 3281 } |
3342 | 3282 |
| 3283 void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each, |
| 3284 Expression* iterable, Statement* body, |
| 3285 int iterable_pos) { |
| 3286 Variable* iterator = |
| 3287 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); |
| 3288 Variable* result = |
| 3289 scope_->NewTemporary(ast_value_factory()->dot_result_string()); |
| 3290 |
| 3291 Expression* assign_iterator; |
| 3292 Expression* next_result; |
| 3293 Expression* result_done; |
| 3294 Expression* assign_each; |
| 3295 |
| 3296 // Hackily disambiguate o from o.next and o [Symbol.iterator](). |
| 3297 // TODO(verwaest): Come up with a better solution. |
| 3298 int get_iterator_pos = iterable_pos != RelocInfo::kNoPosition |
| 3299 ? iterable_pos |
| 3300 : iterable->position() - 2; |
| 3301 int next_result_pos = iterable_pos != RelocInfo::kNoPosition |
| 3302 ? iterable_pos |
| 3303 : iterable->position() - 1; |
| 3304 |
| 3305 // iterator = iterable[Symbol.iterator]() |
| 3306 assign_iterator = factory()->NewAssignment( |
| 3307 Token::ASSIGN, factory()->NewVariableProxy(iterator), |
| 3308 GetIterator(iterable, factory(), get_iterator_pos), iterable->position()); |
| 3309 |
| 3310 // !%_IsJSReceiver(result = iterator.next()) && |
| 3311 // %ThrowIteratorResultNotAnObject(result) |
| 3312 { |
| 3313 // result = iterator.next() |
| 3314 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); |
| 3315 next_result = |
| 3316 BuildIteratorNextResult(iterator_proxy, result, next_result_pos); |
| 3317 } |
| 3318 |
| 3319 // result.done |
| 3320 { |
| 3321 Expression* done_literal = factory()->NewStringLiteral( |
| 3322 ast_value_factory()->done_string(), RelocInfo::kNoPosition); |
| 3323 Expression* result_proxy = factory()->NewVariableProxy(result); |
| 3324 result_done = factory()->NewProperty(result_proxy, done_literal, |
| 3325 RelocInfo::kNoPosition); |
| 3326 } |
| 3327 |
| 3328 // each = result.value |
| 3329 { |
| 3330 Expression* value_literal = factory()->NewStringLiteral( |
| 3331 ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
| 3332 Expression* result_proxy = factory()->NewVariableProxy(result); |
| 3333 Expression* result_value = factory()->NewProperty( |
| 3334 result_proxy, value_literal, RelocInfo::kNoPosition); |
| 3335 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, |
| 3336 RelocInfo::kNoPosition); |
| 3337 if (each->IsArrayLiteral() || each->IsObjectLiteral()) { |
| 3338 DCHECK(allow_harmony_destructuring_assignment()); |
| 3339 assign_each = PatternRewriter::RewriteDestructuringAssignment( |
| 3340 this, assign_each->AsAssignment(), scope_); |
| 3341 } |
| 3342 } |
| 3343 |
| 3344 for_of->Initialize(each, iterable, body, iterator, assign_iterator, |
| 3345 next_result, result_done, assign_each); |
| 3346 } |
| 3347 |
3343 Statement* Parser::DesugarLexicalBindingsInForStatement( | 3348 Statement* Parser::DesugarLexicalBindingsInForStatement( |
3344 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, | 3349 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, |
3345 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 3350 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
3346 Statement* body, bool* ok) { | 3351 Statement* body, bool* ok) { |
3347 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are | 3352 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are |
3348 // copied into a new environment. Moreover, the "next" statement must be | 3353 // copied into a new environment. Moreover, the "next" statement must be |
3349 // evaluated not in the environment of the just completed iteration but in | 3354 // evaluated not in the environment of the just completed iteration but in |
3350 // that of the upcoming one. We achieve this with the following desugaring. | 3355 // that of the upcoming one. We achieve this with the following desugaring. |
3351 // Extra care is needed to preserve the completion value of the original loop. | 3356 // Extra care is needed to preserve the completion value of the original loop. |
3352 // | 3357 // |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3737 each_initialization_block, &descriptor, &decl, | 3742 each_initialization_block, &descriptor, &decl, |
3738 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings | 3743 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings |
3739 : nullptr, | 3744 : nullptr, |
3740 CHECK_OK); | 3745 CHECK_OK); |
3741 } | 3746 } |
3742 | 3747 |
3743 body_block->statements()->Add(each_initialization_block, zone()); | 3748 body_block->statements()->Add(each_initialization_block, zone()); |
3744 body_block->statements()->Add(body, zone()); | 3749 body_block->statements()->Add(body, zone()); |
3745 VariableProxy* temp_proxy = | 3750 VariableProxy* temp_proxy = |
3746 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | 3751 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
3747 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, | 3752 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); |
3748 false); | |
3749 } | 3753 } |
3750 body_scope->set_end_position(scanner()->location().end_pos); | 3754 body_scope->set_end_position(scanner()->location().end_pos); |
3751 body_scope = body_scope->FinalizeBlockScope(); | 3755 body_scope = body_scope->FinalizeBlockScope(); |
3752 body_block->set_scope(body_scope); | 3756 body_block->set_scope(body_scope); |
3753 | 3757 |
3754 // Create a TDZ for any lexically-bound names. | 3758 // Create a TDZ for any lexically-bound names. |
3755 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { | 3759 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { |
3756 DCHECK_NULL(init_block); | 3760 DCHECK_NULL(init_block); |
3757 | 3761 |
3758 init_block = | 3762 init_block = |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3836 RewriteNonPattern(&classifier, CHECK_OK); | 3840 RewriteNonPattern(&classifier, CHECK_OK); |
3837 } else { | 3841 } else { |
3838 enumerable = ParseExpression(true, CHECK_OK); | 3842 enumerable = ParseExpression(true, CHECK_OK); |
3839 } | 3843 } |
3840 | 3844 |
3841 Expect(Token::RPAREN, CHECK_OK); | 3845 Expect(Token::RPAREN, CHECK_OK); |
3842 | 3846 |
3843 // For legacy compat reasons, give for loops similar treatment to | 3847 // For legacy compat reasons, give for loops similar treatment to |
3844 // if statements in allowing a function declaration for a body | 3848 // if statements in allowing a function declaration for a body |
3845 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); | 3849 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); |
3846 InitializeForEachStatement(loop, expression, enumerable, body, | 3850 InitializeForEachStatement(loop, expression, enumerable, body); |
3847 is_destructuring); | |
3848 | 3851 |
3849 Statement* final_loop = loop->IsForOfStatement() | 3852 Statement* final_loop = loop->IsForOfStatement() |
3850 ? FinalizeForOfStatement( | 3853 ? FinalizeForOfStatement( |
3851 loop->AsForOfStatement(), RelocInfo::kNoPosition) | 3854 loop->AsForOfStatement(), RelocInfo::kNoPosition) |
3852 : loop; | 3855 : loop; |
3853 | 3856 |
3854 for_scope->set_end_position(scanner()->location().end_pos); | 3857 for_scope->set_end_position(scanner()->location().end_pos); |
3855 for_scope = for_scope->FinalizeBlockScope(); | 3858 for_scope = for_scope->FinalizeBlockScope(); |
3856 DCHECK(for_scope == nullptr); | 3859 DCHECK(for_scope == nullptr); |
3857 return final_loop; | 3860 return final_loop; |
(...skipping 1794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5652 factory()->NewCallRuntime(Runtime::kAppendElement, | 5655 factory()->NewCallRuntime(Runtime::kAppendElement, |
5653 append_element_args, | 5656 append_element_args, |
5654 RelocInfo::kNoPosition), | 5657 RelocInfo::kNoPosition), |
5655 RelocInfo::kNoPosition), | 5658 RelocInfo::kNoPosition), |
5656 zone()); | 5659 zone()); |
5657 } else { | 5660 } else { |
5658 // If it's a spread, we're adding a for/of loop iterating through it. | 5661 // If it's a spread, we're adding a for/of loop iterating through it. |
5659 Variable* each = | 5662 Variable* each = |
5660 scope_->NewTemporary(ast_value_factory()->dot_for_string()); | 5663 scope_->NewTemporary(ast_value_factory()->dot_for_string()); |
5661 Expression* subject = spread->expression(); | 5664 Expression* subject = spread->expression(); |
5662 Variable* iterator = | |
5663 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); | |
5664 Variable* element = | |
5665 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
5666 // iterator = subject[Symbol.iterator]() | |
5667 Expression* assign_iterator = factory()->NewAssignment( | |
5668 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
5669 GetIterator(subject, factory(), spread->expression_position()), | |
5670 subject->position()); | |
5671 // !%_IsJSReceiver(element = iterator.next()) && | |
5672 // %ThrowIteratorResultNotAnObject(element) | |
5673 Expression* next_element; | |
5674 { | |
5675 // element = iterator.next() | |
5676 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
5677 next_element = BuildIteratorNextResult(iterator_proxy, element, | |
5678 spread->expression_position()); | |
5679 } | |
5680 // element.done | |
5681 Expression* element_done; | |
5682 { | |
5683 Expression* done_literal = factory()->NewStringLiteral( | |
5684 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
5685 Expression* element_proxy = factory()->NewVariableProxy(element); | |
5686 element_done = factory()->NewProperty(element_proxy, done_literal, | |
5687 RelocInfo::kNoPosition); | |
5688 } | |
5689 // each = element.value | |
5690 Expression* assign_each; | |
5691 { | |
5692 Expression* value_literal = factory()->NewStringLiteral( | |
5693 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
5694 Expression* element_proxy = factory()->NewVariableProxy(element); | |
5695 Expression* element_value = factory()->NewProperty( | |
5696 element_proxy, value_literal, RelocInfo::kNoPosition); | |
5697 assign_each = factory()->NewAssignment( | |
5698 Token::ASSIGN, factory()->NewVariableProxy(each), element_value, | |
5699 RelocInfo::kNoPosition); | |
5700 } | |
5701 // %AppendElement($R, each) | 5665 // %AppendElement($R, each) |
5702 Statement* append_body; | 5666 Statement* append_body; |
5703 { | 5667 { |
5704 ZoneList<Expression*>* append_element_args = | 5668 ZoneList<Expression*>* append_element_args = |
5705 NewExpressionList(2, zone()); | 5669 NewExpressionList(2, zone()); |
5706 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | 5670 append_element_args->Add(factory()->NewVariableProxy(result), zone()); |
5707 append_element_args->Add(factory()->NewVariableProxy(each), zone()); | 5671 append_element_args->Add(factory()->NewVariableProxy(each), zone()); |
5708 append_body = factory()->NewExpressionStatement( | 5672 append_body = factory()->NewExpressionStatement( |
5709 factory()->NewCallRuntime(Runtime::kAppendElement, | 5673 factory()->NewCallRuntime(Runtime::kAppendElement, |
5710 append_element_args, | 5674 append_element_args, |
5711 RelocInfo::kNoPosition), | 5675 RelocInfo::kNoPosition), |
5712 RelocInfo::kNoPosition); | 5676 RelocInfo::kNoPosition); |
5713 } | 5677 } |
5714 // for (each of spread) %AppendElement($R, each) | 5678 // for (each of spread) %AppendElement($R, each) |
5715 ForEachStatement* loop = factory()->NewForEachStatement( | 5679 ForEachStatement* loop = factory()->NewForEachStatement( |
5716 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); | 5680 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); |
5717 ForOfStatement* for_of = loop->AsForOfStatement(); | 5681 InitializeForOfStatement(loop->AsForOfStatement(), |
5718 for_of->Initialize(factory()->NewVariableProxy(each), subject, | 5682 factory()->NewVariableProxy(each), subject, |
5719 append_body, iterator, assign_iterator, next_element, | 5683 append_body, spread->expression_position()); |
5720 element_done, assign_each); | 5684 do_block->statements()->Add(loop, zone()); |
5721 do_block->statements()->Add(for_of, zone()); | |
5722 } | 5685 } |
5723 } | 5686 } |
5724 // Now, rewind the original array literal to truncate everything from the | 5687 // Now, rewind the original array literal to truncate everything from the |
5725 // first spread (included) until the end. This fixes $R's initialization. | 5688 // first spread (included) until the end. This fixes $R's initialization. |
5726 lit->RewindSpreads(); | 5689 lit->RewindSpreads(); |
5727 return factory()->NewDoExpression(do_block, result, lit->position()); | 5690 return factory()->NewDoExpression(do_block, result, lit->position()); |
5728 } | 5691 } |
5729 | 5692 |
5730 | 5693 |
5731 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 5694 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
(...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6930 Expression* do_each = | 6893 Expression* do_each = |
6931 factory->NewDoExpression(new_assign_each, var_each, nopos); | 6894 factory->NewDoExpression(new_assign_each, var_each, nopos); |
6932 loop->set_assign_each(do_each); | 6895 loop->set_assign_each(do_each); |
6933 | 6896 |
6934 return final_loop; | 6897 return final_loop; |
6935 } | 6898 } |
6936 | 6899 |
6937 | 6900 |
6938 } // namespace internal | 6901 } // namespace internal |
6939 } // namespace v8 | 6902 } // namespace v8 |
OLD | NEW |