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 3239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3250 throw_arguments->Add(result_proxy_again, zone()); | 3250 throw_arguments->Add(result_proxy_again, zone()); |
3251 Expression* throw_call = factory()->NewCallRuntime( | 3251 Expression* throw_call = factory()->NewCallRuntime( |
3252 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); | 3252 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); |
3253 | 3253 |
3254 return factory()->NewBinaryOperation( | 3254 return factory()->NewBinaryOperation( |
3255 Token::AND, | 3255 Token::AND, |
3256 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), | 3256 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), |
3257 throw_call, pos); | 3257 throw_call, pos); |
3258 } | 3258 } |
3259 | 3259 |
3260 | |
3261 void Parser::InitializeForEachStatement(ForEachStatement* stmt, | 3260 void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
3262 Expression* each, Expression* subject, | 3261 Expression* each, Expression* subject, |
3263 Statement* body, | 3262 Statement* body) { |
3264 bool is_destructuring) { | |
3265 DCHECK(!is_destructuring || allow_harmony_destructuring_assignment()); | |
3266 ForOfStatement* for_of = stmt->AsForOfStatement(); | 3263 ForOfStatement* for_of = stmt->AsForOfStatement(); |
3267 | |
3268 if (for_of != NULL) { | 3264 if (for_of != NULL) { |
3269 Variable* iterator = scope_->NewTemporary( | 3265 InitializeForOfStatement(for_of, each, subject, body, true); |
3270 ast_value_factory()->dot_iterator_string()); | |
3271 Variable* result = scope_->NewTemporary( | |
3272 ast_value_factory()->dot_result_string()); | |
3273 | |
3274 Expression* assign_iterator; | |
3275 Expression* next_result; | |
3276 Expression* result_done; | |
3277 Expression* assign_each; | |
3278 | |
3279 // iterator = subject[Symbol.iterator]() | |
3280 // Hackily disambiguate o from o.next and o [Symbol.iterator](). | |
3281 // TODO(verwaest): Come up with a better solution. | |
3282 assign_iterator = factory()->NewAssignment( | |
3283 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
3284 GetIterator(subject, factory(), subject->position() - 2), | |
3285 subject->position()); | |
3286 | |
3287 // !%_IsJSReceiver(result = iterator.next()) && | |
3288 // %ThrowIteratorResultNotAnObject(result) | |
3289 { | |
3290 // result = iterator.next() | |
3291 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
3292 // Hackily disambiguate o from o.next and o [Symbol.iterator](). | |
3293 // TODO(verwaest): Come up with a better solution. | |
3294 next_result = BuildIteratorNextResult(iterator_proxy, result, | |
3295 subject->position() - 1); | |
3296 } | |
3297 | |
3298 // result.done | |
3299 { | |
3300 Expression* done_literal = factory()->NewStringLiteral( | |
3301 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
3302 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3303 result_done = factory()->NewProperty( | |
3304 result_proxy, done_literal, RelocInfo::kNoPosition); | |
3305 } | |
3306 | |
3307 // each = result.value | |
3308 { | |
3309 Expression* value_literal = factory()->NewStringLiteral( | |
3310 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
3311 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3312 Expression* result_value = factory()->NewProperty( | |
3313 result_proxy, value_literal, RelocInfo::kNoPosition); | |
3314 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | |
3315 RelocInfo::kNoPosition); | |
3316 if (is_destructuring) { | |
3317 assign_each = PatternRewriter::RewriteDestructuringAssignment( | |
3318 this, assign_each->AsAssignment(), scope_); | |
3319 } | |
3320 } | |
3321 | |
3322 for_of->Initialize(each, subject, body, | |
3323 iterator, | |
3324 assign_iterator, | |
3325 next_result, | |
3326 result_done, | |
3327 assign_each); | |
3328 } else { | 3266 } else { |
3329 if (is_destructuring) { | 3267 if (each->IsArrayLiteral() || each->IsObjectLiteral()) { |
3268 DCHECK(allow_harmony_destructuring_assignment()); | |
3330 Variable* temp = | 3269 Variable* temp = |
3331 scope_->NewTemporary(ast_value_factory()->empty_string()); | 3270 scope_->NewTemporary(ast_value_factory()->empty_string()); |
3332 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3271 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
3333 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( | 3272 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( |
3334 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, | 3273 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, |
3335 RelocInfo::kNoPosition), | 3274 RelocInfo::kNoPosition), |
3336 scope_); | 3275 scope_); |
3337 auto block = | 3276 auto block = |
3338 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); | 3277 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); |
3339 block->statements()->Add(factory()->NewExpressionStatement( | 3278 block->statements()->Add(factory()->NewExpressionStatement( |
3340 assign_each, RelocInfo::kNoPosition), | 3279 assign_each, RelocInfo::kNoPosition), |
3341 zone()); | 3280 zone()); |
3342 block->statements()->Add(body, zone()); | 3281 block->statements()->Add(body, zone()); |
3343 body = block; | 3282 body = block; |
3344 each = factory()->NewVariableProxy(temp); | 3283 each = factory()->NewVariableProxy(temp); |
3345 } | 3284 } |
3346 stmt->Initialize(each, subject, body); | 3285 stmt->Initialize(each, subject, body); |
3347 } | 3286 } |
3348 } | 3287 } |
3349 | 3288 |
3289 void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each, | |
3290 Expression* subject, Statement* body, | |
3291 bool use_position_hack) { | |
nickie
2016/03/04 14:15:13
As a fix, I suggest that you replace "bool use_pos
| |
3292 Variable* iterator = | |
3293 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); | |
3294 Variable* result = | |
3295 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
3296 | |
3297 Expression* assign_iterator; | |
3298 Expression* next_result; | |
3299 Expression* result_done; | |
3300 Expression* assign_each; | |
3301 | |
3302 // Hackily disambiguate o from o.next and o [Symbol.iterator](). | |
3303 // TODO(verwaest): Come up with a better solution. | |
3304 int get_iterator_pos = subject->position() - (use_position_hack * 2); | |
3305 int next_result_pos = subject->position() - (use_position_hack * 1); | |
nickie
2016/03/04 14:15:13
These two would become:
int get_iterator_pos =
| |
3306 | |
3307 // iterator = subject[Symbol.iterator]() | |
3308 assign_iterator = factory()->NewAssignment( | |
3309 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
3310 GetIterator(subject, factory(), get_iterator_pos), subject->position()); | |
3311 | |
3312 // !%_IsJSReceiver(result = iterator.next()) && | |
3313 // %ThrowIteratorResultNotAnObject(result) | |
3314 { | |
3315 // result = iterator.next() | |
3316 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
3317 next_result = | |
3318 BuildIteratorNextResult(iterator_proxy, result, next_result_pos); | |
3319 } | |
3320 | |
3321 // result.done | |
3322 { | |
3323 Expression* done_literal = factory()->NewStringLiteral( | |
3324 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
3325 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3326 result_done = factory()->NewProperty(result_proxy, done_literal, | |
3327 RelocInfo::kNoPosition); | |
3328 } | |
3329 | |
3330 // each = result.value | |
3331 { | |
3332 Expression* value_literal = factory()->NewStringLiteral( | |
3333 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
3334 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3335 Expression* result_value = factory()->NewProperty( | |
3336 result_proxy, value_literal, RelocInfo::kNoPosition); | |
3337 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | |
3338 RelocInfo::kNoPosition); | |
3339 if (each->IsArrayLiteral() || each->IsObjectLiteral()) { | |
3340 DCHECK(allow_harmony_destructuring_assignment()); | |
3341 assign_each = PatternRewriter::RewriteDestructuringAssignment( | |
3342 this, assign_each->AsAssignment(), scope_); | |
3343 } | |
3344 } | |
3345 | |
3346 for_of->Initialize(each, subject, body, iterator, assign_iterator, | |
3347 next_result, result_done, assign_each); | |
3348 } | |
3349 | |
3350 Statement* Parser::DesugarLexicalBindingsInForStatement( | 3350 Statement* Parser::DesugarLexicalBindingsInForStatement( |
3351 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, | 3351 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, |
3352 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 3352 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
3353 Statement* body, bool* ok) { | 3353 Statement* body, bool* ok) { |
3354 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are | 3354 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are |
3355 // copied into a new environment. Moreover, the "next" statement must be | 3355 // copied into a new environment. Moreover, the "next" statement must be |
3356 // evaluated not in the environment of the just completed iteration but in | 3356 // evaluated not in the environment of the just completed iteration but in |
3357 // that of the upcoming one. We achieve this with the following desugaring. | 3357 // that of the upcoming one. We achieve this with the following desugaring. |
3358 // Extra care is needed to preserve the completion value of the original loop. | 3358 // Extra care is needed to preserve the completion value of the original loop. |
3359 // | 3359 // |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3722 each_initialization_block, &descriptor, &decl, | 3722 each_initialization_block, &descriptor, &decl, |
3723 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings | 3723 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings |
3724 : nullptr, | 3724 : nullptr, |
3725 CHECK_OK); | 3725 CHECK_OK); |
3726 } | 3726 } |
3727 | 3727 |
3728 body_block->statements()->Add(each_initialization_block, zone()); | 3728 body_block->statements()->Add(each_initialization_block, zone()); |
3729 body_block->statements()->Add(body, zone()); | 3729 body_block->statements()->Add(body, zone()); |
3730 VariableProxy* temp_proxy = | 3730 VariableProxy* temp_proxy = |
3731 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | 3731 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
3732 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, | 3732 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); |
3733 false); | |
3734 } | 3733 } |
3735 body_scope->set_end_position(scanner()->location().end_pos); | 3734 body_scope->set_end_position(scanner()->location().end_pos); |
3736 body_scope = body_scope->FinalizeBlockScope(); | 3735 body_scope = body_scope->FinalizeBlockScope(); |
3737 body_block->set_scope(body_scope); | 3736 body_block->set_scope(body_scope); |
3738 | 3737 |
3739 // Create a TDZ for any lexically-bound names. | 3738 // Create a TDZ for any lexically-bound names. |
3740 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { | 3739 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { |
3741 DCHECK_NULL(init_block); | 3740 DCHECK_NULL(init_block); |
3742 | 3741 |
3743 init_block = | 3742 init_block = |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3831 // lexical binding is introduced which overlaps with the for-in/of, | 3830 // lexical binding is introduced which overlaps with the for-in/of, |
3832 // expressions in head of the loop should actually have variables | 3831 // expressions in head of the loop should actually have variables |
3833 // resolved in the outer scope. | 3832 // resolved in the outer scope. |
3834 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); | 3833 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); |
3835 { | 3834 { |
3836 BlockState block_state(&scope_, body_scope); | 3835 BlockState block_state(&scope_, body_scope); |
3837 Block* block = | 3836 Block* block = |
3838 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 3837 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
3839 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3838 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3840 block->statements()->Add(body, zone()); | 3839 block->statements()->Add(body, zone()); |
3841 InitializeForEachStatement(loop, expression, enumerable, block, | 3840 InitializeForEachStatement(loop, expression, enumerable, block); |
3842 is_destructuring); | |
3843 body_scope->set_end_position(scanner()->location().end_pos); | 3841 body_scope->set_end_position(scanner()->location().end_pos); |
3844 body_scope = body_scope->FinalizeBlockScope(); | 3842 body_scope = body_scope->FinalizeBlockScope(); |
3845 block->set_scope(body_scope); | 3843 block->set_scope(body_scope); |
3846 } | 3844 } |
3847 | 3845 |
3848 Statement* final_loop = loop->IsForOfStatement() | 3846 Statement* final_loop = loop->IsForOfStatement() |
3849 ? FinalizeForOfStatement( | 3847 ? FinalizeForOfStatement( |
3850 loop->AsForOfStatement(), RelocInfo::kNoPosition) | 3848 loop->AsForOfStatement(), RelocInfo::kNoPosition) |
3851 : loop; | 3849 : loop; |
3852 | 3850 |
(...skipping 1807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5660 factory()->NewCallRuntime(Runtime::kAppendElement, | 5658 factory()->NewCallRuntime(Runtime::kAppendElement, |
5661 append_element_args, | 5659 append_element_args, |
5662 RelocInfo::kNoPosition), | 5660 RelocInfo::kNoPosition), |
5663 RelocInfo::kNoPosition), | 5661 RelocInfo::kNoPosition), |
5664 zone()); | 5662 zone()); |
5665 } else { | 5663 } else { |
5666 // If it's a spread, we're adding a for/of loop iterating through it. | 5664 // If it's a spread, we're adding a for/of loop iterating through it. |
5667 Variable* each = | 5665 Variable* each = |
5668 scope_->NewTemporary(ast_value_factory()->dot_for_string()); | 5666 scope_->NewTemporary(ast_value_factory()->dot_for_string()); |
5669 Expression* subject = spread->expression(); | 5667 Expression* subject = spread->expression(); |
5670 Variable* iterator = | |
5671 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); | |
5672 Variable* element = | |
5673 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
5674 // iterator = subject[Symbol.iterator]() | |
5675 Expression* assign_iterator = factory()->NewAssignment( | |
5676 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
5677 GetIterator(subject, factory(), spread->expression_position()), | |
nickie
2016/03/04 14:15:13
There was another tricky point but it was a bit hi
| |
5678 subject->position()); | |
5679 // !%_IsJSReceiver(element = iterator.next()) && | |
5680 // %ThrowIteratorResultNotAnObject(element) | |
5681 Expression* next_element; | |
5682 { | |
5683 // element = iterator.next() | |
5684 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
5685 next_element = BuildIteratorNextResult(iterator_proxy, element, | |
5686 spread->expression_position()); | |
nickie
2016/03/04 14:15:13
Here too...
| |
5687 } | |
5688 // element.done | |
5689 Expression* element_done; | |
5690 { | |
5691 Expression* done_literal = factory()->NewStringLiteral( | |
5692 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
5693 Expression* element_proxy = factory()->NewVariableProxy(element); | |
5694 element_done = factory()->NewProperty(element_proxy, done_literal, | |
5695 RelocInfo::kNoPosition); | |
5696 } | |
5697 // each = element.value | |
5698 Expression* assign_each; | |
5699 { | |
5700 Expression* value_literal = factory()->NewStringLiteral( | |
5701 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
5702 Expression* element_proxy = factory()->NewVariableProxy(element); | |
5703 Expression* element_value = factory()->NewProperty( | |
5704 element_proxy, value_literal, RelocInfo::kNoPosition); | |
5705 assign_each = factory()->NewAssignment( | |
5706 Token::ASSIGN, factory()->NewVariableProxy(each), element_value, | |
5707 RelocInfo::kNoPosition); | |
5708 } | |
5709 // %AppendElement($R, each) | 5668 // %AppendElement($R, each) |
5710 Statement* append_body; | 5669 Statement* append_body; |
5711 { | 5670 { |
5712 ZoneList<Expression*>* append_element_args = | 5671 ZoneList<Expression*>* append_element_args = |
5713 NewExpressionList(2, zone()); | 5672 NewExpressionList(2, zone()); |
5714 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | 5673 append_element_args->Add(factory()->NewVariableProxy(result), zone()); |
5715 append_element_args->Add(factory()->NewVariableProxy(each), zone()); | 5674 append_element_args->Add(factory()->NewVariableProxy(each), zone()); |
5716 append_body = factory()->NewExpressionStatement( | 5675 append_body = factory()->NewExpressionStatement( |
5717 factory()->NewCallRuntime(Runtime::kAppendElement, | 5676 factory()->NewCallRuntime(Runtime::kAppendElement, |
5718 append_element_args, | 5677 append_element_args, |
5719 RelocInfo::kNoPosition), | 5678 RelocInfo::kNoPosition), |
5720 RelocInfo::kNoPosition); | 5679 RelocInfo::kNoPosition); |
5721 } | 5680 } |
5722 // for (each of spread) %AppendElement($R, each) | 5681 // for (each of spread) %AppendElement($R, each) |
5723 ForEachStatement* loop = factory()->NewForEachStatement( | 5682 ForEachStatement* loop = factory()->NewForEachStatement( |
5724 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); | 5683 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); |
5725 ForOfStatement* for_of = loop->AsForOfStatement(); | 5684 InitializeForOfStatement(loop->AsForOfStatement(), |
5726 for_of->Initialize(factory()->NewVariableProxy(each), subject, | 5685 factory()->NewVariableProxy(each), subject, |
5727 append_body, iterator, assign_iterator, next_element, | 5686 append_body); |
5728 element_done, assign_each); | 5687 do_block->statements()->Add(loop, zone()); |
5729 do_block->statements()->Add(for_of, zone()); | |
5730 } | 5688 } |
5731 } | 5689 } |
5732 // Now, rewind the original array literal to truncate everything from the | 5690 // Now, rewind the original array literal to truncate everything from the |
5733 // first spread (included) until the end. This fixes $R's initialization. | 5691 // first spread (included) until the end. This fixes $R's initialization. |
5734 lit->RewindSpreads(); | 5692 lit->RewindSpreads(); |
5735 return factory()->NewDoExpression(do_block, result, lit->position()); | 5693 return factory()->NewDoExpression(do_block, result, lit->position()); |
5736 } | 5694 } |
5737 | 5695 |
5738 | 5696 |
5739 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 5697 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6940 Expression* do_each = | 6898 Expression* do_each = |
6941 factory->NewDoExpression(new_assign_each, var_each, nopos); | 6899 factory->NewDoExpression(new_assign_each, var_each, nopos); |
6942 loop->set_assign_each(do_each); | 6900 loop->set_assign_each(do_each); |
6943 | 6901 |
6944 return final_loop; | 6902 return final_loop; |
6945 } | 6903 } |
6946 | 6904 |
6947 | 6905 |
6948 } // namespace internal | 6906 } // namespace internal |
6949 } // namespace v8 | 6907 } // namespace v8 |
OLD | NEW |