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 3318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3329 result_proxy, value_literal, RelocInfo::kNoPosition); | 3329 result_proxy, value_literal, RelocInfo::kNoPosition); |
3330 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | 3330 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, |
3331 RelocInfo::kNoPosition); | 3331 RelocInfo::kNoPosition); |
3332 if (is_destructuring) { | 3332 if (is_destructuring) { |
3333 assign_each = PatternRewriter::RewriteDestructuringAssignment( | 3333 assign_each = PatternRewriter::RewriteDestructuringAssignment( |
3334 this, assign_each->AsAssignment(), scope_); | 3334 this, assign_each->AsAssignment(), scope_); |
3335 } | 3335 } |
3336 } | 3336 } |
3337 | 3337 |
3338 for_of->Initialize(each, subject, body, | 3338 for_of->Initialize(each, subject, body, |
3339 iterator, | |
3339 assign_iterator, | 3340 assign_iterator, |
3340 next_result, | 3341 next_result, |
3341 result_done, | 3342 result_done, |
3342 assign_each); | 3343 assign_each); |
3343 } else { | 3344 } else { |
3344 if (is_destructuring) { | 3345 if (is_destructuring) { |
3345 Variable* temp = | 3346 Variable* temp = |
3346 scope_->NewTemporary(ast_value_factory()->empty_string()); | 3347 scope_->NewTemporary(ast_value_factory()->empty_string()); |
3347 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3348 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
3348 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( | 3349 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3606 inner_block->set_scope(inner_scope); | 3607 inner_block->set_scope(inner_scope); |
3607 } | 3608 } |
3608 | 3609 |
3609 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | 3610 outer_loop->Initialize(NULL, NULL, NULL, inner_block); |
3610 return outer_block; | 3611 return outer_block; |
3611 } | 3612 } |
3612 | 3613 |
3613 | 3614 |
3614 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3615 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
3615 bool* ok) { | 3616 bool* ok) { |
3616 // ForStatement :: | |
3617 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | |
3618 | |
3619 int stmt_pos = peek_position(); | 3617 int stmt_pos = peek_position(); |
3620 Statement* init = NULL; | 3618 Statement* init = NULL; |
3621 ZoneList<const AstRawString*> lexical_bindings(1, zone()); | 3619 ZoneList<const AstRawString*> lexical_bindings(1, zone()); |
3622 | 3620 |
3623 // Create an in-between scope for let-bound iteration variables. | 3621 // Create an in-between scope for let-bound iteration variables. |
3624 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3622 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3625 | 3623 |
3626 BlockState block_state(&scope_, for_scope); | 3624 BlockState block_state(&scope_, for_scope); |
3627 Expect(Token::FOR, CHECK_OK); | 3625 Expect(Token::FOR, CHECK_OK); |
3628 Expect(Token::LPAREN, CHECK_OK); | 3626 Expect(Token::LPAREN, CHECK_OK); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3745 | 3743 |
3746 body_block->statements()->Add(each_initialization_block, zone()); | 3744 body_block->statements()->Add(each_initialization_block, zone()); |
3747 body_block->statements()->Add(body, zone()); | 3745 body_block->statements()->Add(body, zone()); |
3748 VariableProxy* temp_proxy = | 3746 VariableProxy* temp_proxy = |
3749 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | 3747 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
3750 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, | 3748 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, |
3751 false); | 3749 false); |
3752 } | 3750 } |
3753 body_scope->set_end_position(scanner()->location().end_pos); | 3751 body_scope->set_end_position(scanner()->location().end_pos); |
3754 body_scope = body_scope->FinalizeBlockScope(); | 3752 body_scope = body_scope->FinalizeBlockScope(); |
3755 body_block->set_scope(body_scope); | 3753 body_block->set_scope(body_scope); |
3756 | 3754 |
3757 // Create a TDZ for any lexically-bound names. | 3755 // Create a TDZ for any lexically-bound names. |
3758 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { | 3756 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { |
3759 DCHECK_NULL(init_block); | 3757 DCHECK_NULL(init_block); |
3760 | 3758 |
3761 init_block = | 3759 init_block = |
3762 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition); | 3760 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition); |
3763 | 3761 |
3764 for (int i = 0; i < lexical_bindings.length(); ++i) { | 3762 for (int i = 0; i < lexical_bindings.length(); ++i) { |
3765 // TODO(adamk): This needs to be some sort of special | 3763 // TODO(adamk): This needs to be some sort of special |
3766 // INTERNAL variable that's invisible to the debugger | 3764 // INTERNAL variable that's invisible to the debugger |
3767 // but visible to everything else. | 3765 // but visible to everything else. |
3768 VariableProxy* tdz_proxy = | 3766 VariableProxy* tdz_proxy = |
3769 NewUnresolved(lexical_bindings[i], LET); | 3767 NewUnresolved(lexical_bindings[i], LET); |
3770 Declaration* tdz_decl = factory()->NewVariableDeclaration( | 3768 Declaration* tdz_decl = factory()->NewVariableDeclaration( |
3771 tdz_proxy, LET, scope_, RelocInfo::kNoPosition); | 3769 tdz_proxy, LET, scope_, RelocInfo::kNoPosition); |
3772 Variable* tdz_var = Declare( | 3770 Variable* tdz_var = Declare( |
3773 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK); | 3771 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
3774 tdz_var->set_initializer_position(position()); | 3772 tdz_var->set_initializer_position(position()); |
3775 } | |
3776 } | 3773 } |
3774 } | |
3775 | |
3776 Statement* final_loop = loop->IsForOfStatement() | |
3777 ? FinalizeForOfStatement( | |
3778 loop->AsForOfStatement(), RelocInfo::kNoPosition) | |
3779 : loop; | |
Dan Ehrenberg
2016/02/16 21:18:30
I'm not sure if any of this is risky (the nopos pa
rossberg
2016/02/17 12:54:45
Good point, added flag.
| |
3777 | 3780 |
3778 for_scope->set_end_position(scanner()->location().end_pos); | 3781 for_scope->set_end_position(scanner()->location().end_pos); |
3779 for_scope = for_scope->FinalizeBlockScope(); | 3782 for_scope = for_scope->FinalizeBlockScope(); |
3780 // Parsed for-in loop w/ variable declarations. | 3783 // Parsed for-in loop w/ variable declarations. |
3781 if (init_block != nullptr) { | 3784 if (init_block != nullptr) { |
3782 init_block->statements()->Add(loop, zone()); | 3785 init_block->statements()->Add(final_loop, zone()); |
3783 init_block->set_scope(for_scope); | 3786 init_block->set_scope(for_scope); |
3784 return init_block; | 3787 return init_block; |
3785 } else { | 3788 } else { |
3786 DCHECK_NULL(for_scope); | 3789 DCHECK_NULL(for_scope); |
3787 return loop; | 3790 return final_loop; |
3788 } | 3791 } |
3789 } else { | 3792 } else { |
3790 init = parsing_result.BuildInitializationBlock( | 3793 init = parsing_result.BuildInitializationBlock( |
3791 IsLexicalVariableMode(parsing_result.descriptor.mode) | 3794 IsLexicalVariableMode(parsing_result.descriptor.mode) |
3792 ? &lexical_bindings | 3795 ? &lexical_bindings |
3793 : nullptr, | 3796 : nullptr, |
3794 CHECK_OK); | 3797 CHECK_OK); |
3795 } | 3798 } |
3796 } else { | 3799 } else { |
3797 int lhs_beg_pos = peek_position(); | 3800 int lhs_beg_pos = peek_position(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3840 | 3843 |
3841 Expect(Token::RPAREN, CHECK_OK); | 3844 Expect(Token::RPAREN, CHECK_OK); |
3842 | 3845 |
3843 // Make a block around the statement in case a lexical binding | 3846 // Make a block around the statement in case a lexical binding |
3844 // is introduced, e.g. by a FunctionDeclaration. | 3847 // is introduced, e.g. by a FunctionDeclaration. |
3845 // This block must not use for_scope as its scope because if a | 3848 // This block must not use for_scope as its scope because if a |
3846 // lexical binding is introduced which overlaps with the for-in/of, | 3849 // lexical binding is introduced which overlaps with the for-in/of, |
3847 // expressions in head of the loop should actually have variables | 3850 // expressions in head of the loop should actually have variables |
3848 // resolved in the outer scope. | 3851 // resolved in the outer scope. |
3849 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); | 3852 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); |
3850 BlockState block_state(&scope_, body_scope); | 3853 { |
3851 Block* block = | 3854 BlockState block_state(&scope_, body_scope); |
3852 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 3855 Block* block = |
3853 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3856 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
3854 block->statements()->Add(body, zone()); | 3857 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3855 InitializeForEachStatement(loop, expression, enumerable, block, | 3858 block->statements()->Add(body, zone()); |
3856 is_destructuring); | 3859 InitializeForEachStatement(loop, expression, enumerable, block, |
3857 body_scope->set_end_position(scanner()->location().end_pos); | 3860 is_destructuring); |
3858 body_scope = body_scope->FinalizeBlockScope(); | 3861 body_scope->set_end_position(scanner()->location().end_pos); |
3859 block->set_scope(body_scope); | 3862 body_scope = body_scope->FinalizeBlockScope(); |
3863 block->set_scope(body_scope); | |
3864 } | |
3865 | |
3866 Statement* final_loop = loop->IsForOfStatement() | |
3867 ? FinalizeForOfStatement( | |
3868 loop->AsForOfStatement(), RelocInfo::kNoPosition) | |
3869 : loop; | |
3870 | |
3860 for_scope->set_end_position(scanner()->location().end_pos); | 3871 for_scope->set_end_position(scanner()->location().end_pos); |
3861 for_scope = for_scope->FinalizeBlockScope(); | 3872 for_scope = for_scope->FinalizeBlockScope(); |
3862 DCHECK(for_scope == nullptr); | 3873 DCHECK(for_scope == nullptr); |
3863 // Parsed for-in loop. | 3874 return final_loop; |
3864 return loop; | |
3865 | 3875 |
3866 } else { | 3876 } else { |
3867 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); | 3877 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); |
3868 } | 3878 } |
3869 } | 3879 } |
3870 } | 3880 } |
3871 | 3881 |
3872 // Standard 'for' loop | 3882 // Standard 'for' loop |
3873 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); | 3883 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); |
3874 Target target(&this->target_stack_, loop); | 3884 Target target(&this->target_stack_, loop); |
(...skipping 1859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5734 factory()->NewCallRuntime(Runtime::kAppendElement, | 5744 factory()->NewCallRuntime(Runtime::kAppendElement, |
5735 append_element_args, | 5745 append_element_args, |
5736 RelocInfo::kNoPosition), | 5746 RelocInfo::kNoPosition), |
5737 RelocInfo::kNoPosition); | 5747 RelocInfo::kNoPosition); |
5738 } | 5748 } |
5739 // for (each of spread) %AppendElement($R, each) | 5749 // for (each of spread) %AppendElement($R, each) |
5740 ForEachStatement* loop = factory()->NewForEachStatement( | 5750 ForEachStatement* loop = factory()->NewForEachStatement( |
5741 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); | 5751 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); |
5742 ForOfStatement* for_of = loop->AsForOfStatement(); | 5752 ForOfStatement* for_of = loop->AsForOfStatement(); |
5743 for_of->Initialize(factory()->NewVariableProxy(each), subject, | 5753 for_of->Initialize(factory()->NewVariableProxy(each), subject, |
5744 append_body, assign_iterator, next_element, | 5754 append_body, iterator, assign_iterator, next_element, |
5745 element_done, assign_each); | 5755 element_done, assign_each); |
5746 do_block->statements()->Add(for_of, zone()); | 5756 do_block->statements()->Add(for_of, zone()); |
5747 } | 5757 } |
5748 } | 5758 } |
5749 // Now, rewind the original array literal to truncate everything from the | 5759 // Now, rewind the original array literal to truncate everything from the |
5750 // first spread (included) until the end. This fixes $R's initialization. | 5760 // first spread (included) until the end. This fixes $R's initialization. |
5751 lit->RewindSpreads(); | 5761 lit->RewindSpreads(); |
5752 return factory()->NewDoExpression(do_block, result, lit->position()); | 5762 return factory()->NewDoExpression(do_block, result, lit->position()); |
5753 } | 5763 } |
5754 | 5764 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5892 Expression* ParserTraits::RewriteYieldStar( | 5902 Expression* ParserTraits::RewriteYieldStar( |
5893 Expression* generator, Expression* iterable, int pos) { | 5903 Expression* generator, Expression* iterable, int pos) { |
5894 | 5904 |
5895 const int nopos = RelocInfo::kNoPosition; | 5905 const int nopos = RelocInfo::kNoPosition; |
5896 | 5906 |
5897 auto factory = parser_->factory(); | 5907 auto factory = parser_->factory(); |
5898 auto avfactory = parser_->ast_value_factory(); | 5908 auto avfactory = parser_->ast_value_factory(); |
5899 auto scope = parser_->scope_; | 5909 auto scope = parser_->scope_; |
5900 auto zone = parser_->zone(); | 5910 auto zone = parser_->zone(); |
5901 | 5911 |
5902 Statement* skip = factory->NewEmptyStatement(nopos); | |
5903 | 5912 |
5904 // Forward definition for break/continue statements. | 5913 // Forward definition for break/continue statements. |
5905 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos); | 5914 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos); |
5906 | 5915 |
5907 | 5916 |
5908 // let input = undefined; | 5917 // let input = undefined; |
5909 Variable* var_input = scope->NewTemporary(avfactory->empty_string()); | 5918 Variable* var_input = scope->NewTemporary(avfactory->empty_string()); |
5910 Statement* initialize_input; | 5919 Statement* initialize_input; |
5911 { | 5920 { |
5912 Expression* input_proxy = factory->NewVariableProxy(var_input); | 5921 Expression* input_proxy = factory->NewVariableProxy(var_input); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5964 } | 5973 } |
5965 | 5974 |
5966 Statement* throw_call; | 5975 Statement* throw_call; |
5967 { | 5976 { |
5968 Expression* call = NewThrowTypeError( | 5977 Expression* call = NewThrowTypeError( |
5969 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(), | 5978 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(), |
5970 nopos); | 5979 nopos); |
5971 throw_call = factory->NewExpressionStatement(call, nopos); | 5980 throw_call = factory->NewExpressionStatement(call, nopos); |
5972 } | 5981 } |
5973 | 5982 |
5974 validate_iterator = | 5983 validate_iterator = factory->NewIfStatement( |
5975 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | 5984 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
5976 } | 5985 } |
5977 | 5986 |
5978 | 5987 |
5979 // output = iterator.next(input); | 5988 // output = iterator.next(input); |
5980 Statement* call_next; | 5989 Statement* call_next; |
5981 { | 5990 { |
5982 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); | 5991 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); |
5983 Expression* literal = | 5992 Expression* literal = |
5984 factory->NewStringLiteral(avfactory->next_string(), nopos); | 5993 factory->NewStringLiteral(avfactory->next_string(), nopos); |
5985 Expression* next_property = | 5994 Expression* next_property = |
(...skipping 22 matching lines...) Expand all Loading... | |
6008 | 6017 |
6009 Statement* throw_call; | 6018 Statement* throw_call; |
6010 { | 6019 { |
6011 auto args = new (zone) ZoneList<Expression*>(1, zone); | 6020 auto args = new (zone) ZoneList<Expression*>(1, zone); |
6012 args->Add(factory->NewVariableProxy(var_output), zone); | 6021 args->Add(factory->NewVariableProxy(var_output), zone); |
6013 Expression* call = factory->NewCallRuntime( | 6022 Expression* call = factory->NewCallRuntime( |
6014 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | 6023 Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
6015 throw_call = factory->NewExpressionStatement(call, nopos); | 6024 throw_call = factory->NewExpressionStatement(call, nopos); |
6016 } | 6025 } |
6017 | 6026 |
6018 validate_next_output = | 6027 validate_next_output = factory->NewIfStatement( |
6019 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | 6028 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
6020 } | 6029 } |
6021 | 6030 |
6022 | 6031 |
6023 // let iteratorThrow = iterator.throw; | 6032 // let iteratorThrow = iterator.throw; |
6024 Variable* var_throw = scope->NewTemporary(avfactory->empty_string()); | 6033 Variable* var_throw = scope->NewTemporary(avfactory->empty_string()); |
6025 Statement* get_throw; | 6034 Statement* get_throw; |
6026 { | 6035 { |
6027 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); | 6036 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); |
6028 Expression* literal = | 6037 Expression* literal = |
6029 factory->NewStringLiteral(avfactory->throw_string(), nopos); | 6038 factory->NewStringLiteral(avfactory->throw_string(), nopos); |
(...skipping 15 matching lines...) Expand all Loading... | |
6045 Expression* condition = factory->NewCompareOperation( | 6054 Expression* condition = factory->NewCompareOperation( |
6046 Token::EQ, factory->NewVariableProxy(var_throw), | 6055 Token::EQ, factory->NewVariableProxy(var_throw), |
6047 factory->NewNullLiteral(nopos), nopos); | 6056 factory->NewNullLiteral(nopos), nopos); |
6048 | 6057 |
6049 Expression* call = NewThrowTypeError( | 6058 Expression* call = NewThrowTypeError( |
6050 MessageTemplate::kThrowMethodMissing, | 6059 MessageTemplate::kThrowMethodMissing, |
6051 avfactory->empty_string(), nopos); | 6060 avfactory->empty_string(), nopos); |
6052 Statement* throw_call = factory->NewExpressionStatement(call, nopos); | 6061 Statement* throw_call = factory->NewExpressionStatement(call, nopos); |
6053 | 6062 |
6054 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); | 6063 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); |
6055 BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>(), | 6064 Variable* var_tmp = scope->NewTemporary(avfactory->empty_string()); |
6056 Nothing<Variable*>()); | 6065 BuildIteratorClose( |
6066 then->statements(), var_iterator, Nothing<Variable*>(), var_tmp); | |
6057 then->statements()->Add(throw_call, zone); | 6067 then->statements()->Add(throw_call, zone); |
6058 check_throw = | 6068 check_throw = factory->NewIfStatement( |
6059 factory->NewIfStatement(condition, then, skip, nopos); | 6069 condition, then, factory->NewEmptyStatement(nopos), nopos); |
6060 } | 6070 } |
6061 | 6071 |
6062 | 6072 |
6063 // output = %_Call(iteratorThrow, iterator, input); | 6073 // output = %_Call(iteratorThrow, iterator, input); |
6064 Statement* call_throw; | 6074 Statement* call_throw; |
6065 { | 6075 { |
6066 auto args = new (zone) ZoneList<Expression*>(3, zone); | 6076 auto args = new (zone) ZoneList<Expression*>(3, zone); |
6067 args->Add(factory->NewVariableProxy(var_throw), zone); | 6077 args->Add(factory->NewVariableProxy(var_throw), zone); |
6068 args->Add(factory->NewVariableProxy(var_iterator), zone); | 6078 args->Add(factory->NewVariableProxy(var_iterator), zone); |
6069 args->Add(factory->NewVariableProxy(var_input), zone); | 6079 args->Add(factory->NewVariableProxy(var_input), zone); |
(...skipping 18 matching lines...) Expand all Loading... | |
6088 | 6098 |
6089 Statement* throw_call; | 6099 Statement* throw_call; |
6090 { | 6100 { |
6091 auto args = new (zone) ZoneList<Expression*>(1, zone); | 6101 auto args = new (zone) ZoneList<Expression*>(1, zone); |
6092 args->Add(factory->NewVariableProxy(var_output), zone); | 6102 args->Add(factory->NewVariableProxy(var_output), zone); |
6093 Expression* call = factory->NewCallRuntime( | 6103 Expression* call = factory->NewCallRuntime( |
6094 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | 6104 Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
6095 throw_call = factory->NewExpressionStatement(call, nopos); | 6105 throw_call = factory->NewExpressionStatement(call, nopos); |
6096 } | 6106 } |
6097 | 6107 |
6098 validate_throw_output = | 6108 validate_throw_output = factory->NewIfStatement( |
6099 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | 6109 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
6100 } | 6110 } |
6101 | 6111 |
6102 | 6112 |
6103 // if (output.done) break; | 6113 // if (output.done) break; |
6104 Statement* if_done; | 6114 Statement* if_done; |
6105 { | 6115 { |
6106 Expression* output_proxy = factory->NewVariableProxy(var_output); | 6116 Expression* output_proxy = factory->NewVariableProxy(var_output); |
6107 Expression* literal = | 6117 Expression* literal = |
6108 factory->NewStringLiteral(avfactory->done_string(), nopos); | 6118 factory->NewStringLiteral(avfactory->done_string(), nopos); |
6109 Expression* property = factory->NewProperty(output_proxy, literal, nopos); | 6119 Expression* property = factory->NewProperty(output_proxy, literal, nopos); |
6110 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos); | 6120 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos); |
6111 if_done = factory->NewIfStatement(property, break_loop, skip, nopos); | 6121 if_done = factory->NewIfStatement( |
6122 property, break_loop, factory->NewEmptyStatement(nopos), nopos); | |
6112 } | 6123 } |
6113 | 6124 |
6114 | 6125 |
6115 // mode = kReturn; | 6126 // mode = kReturn; |
6116 Statement* set_mode_return; | 6127 Statement* set_mode_return; |
6117 { | 6128 { |
6118 Expression* mode_proxy = factory->NewVariableProxy(var_mode); | 6129 Expression* mode_proxy = factory->NewVariableProxy(var_mode); |
6119 Expression* kreturn = | 6130 Expression* kreturn = |
6120 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos); | 6131 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos); |
6121 Expression* assignment = | 6132 Expression* assignment = |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6220 | 6231 |
6221 // switch (mode) { ... } | 6232 // switch (mode) { ... } |
6222 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos); | 6233 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos); |
6223 { | 6234 { |
6224 auto case_next = new (zone) ZoneList<Statement*>(3, zone); | 6235 auto case_next = new (zone) ZoneList<Statement*>(3, zone); |
6225 case_next->Add(call_next, zone); | 6236 case_next->Add(call_next, zone); |
6226 case_next->Add(validate_next_output, zone); | 6237 case_next->Add(validate_next_output, zone); |
6227 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | 6238 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
6228 | 6239 |
6229 auto case_return = new (zone) ZoneList<Statement*>(5, zone); | 6240 auto case_return = new (zone) ZoneList<Statement*>(5, zone); |
6230 BuildIteratorClose( | 6241 BuildIteratorClose(case_return, var_iterator, Just(var_input), var_output); |
6231 case_return, var_iterator, Just(var_input), Just(var_output)); | |
6232 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | 6242 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
6233 | 6243 |
6234 auto case_throw = new (zone) ZoneList<Statement*>(5, zone); | 6244 auto case_throw = new (zone) ZoneList<Statement*>(5, zone); |
6235 case_throw->Add(get_throw, zone); | 6245 case_throw->Add(get_throw, zone); |
6236 case_throw->Add(check_throw, zone); | 6246 case_throw->Add(check_throw, zone); |
6237 case_throw->Add(call_throw, zone); | 6247 case_throw->Add(call_throw, zone); |
6238 case_throw->Add(validate_throw_output, zone); | 6248 case_throw->Add(validate_throw_output, zone); |
6239 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | 6249 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
6240 | 6250 |
6241 auto cases = new (zone) ZoneList<CaseClause*>(3, zone); | 6251 auto cases = new (zone) ZoneList<CaseClause*>(3, zone); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6288 Rewriter::Rewrite(parser_, yield_star, avfactory); | 6298 Rewriter::Rewrite(parser_, yield_star, avfactory); |
6289 } | 6299 } |
6290 | 6300 |
6291 return yield_star; | 6301 return yield_star; |
6292 } | 6302 } |
6293 | 6303 |
6294 | 6304 |
6295 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, | 6305 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
6296 Variable* iterator, | 6306 Variable* iterator, |
6297 Maybe<Variable*> input, | 6307 Maybe<Variable*> input, |
6298 Maybe<Variable*> output) { | 6308 Variable* var_output) { |
6309 // | |
6310 // This function adds four statements to [statements], corresponding to the | |
6311 // following code: | |
6312 // | |
6313 // let iteratorReturn = iterator.return; | |
6314 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|; | |
6315 // output = %_Call(iteratorReturn, iterator|, input|); | |
6316 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
6317 // | |
6318 // Here, |...| denotes optional parts, depending on the presence of the | |
Dan Ehrenberg
2016/02/16 21:18:30
Given the below comment (iteratorReturn shouldn't
rossberg
2016/02/17 12:54:45
Done.
| |
6319 // input variable. | |
6320 // | |
6321 | |
6299 const int nopos = RelocInfo::kNoPosition; | 6322 const int nopos = RelocInfo::kNoPosition; |
6300 auto factory = parser_->factory(); | 6323 auto factory = parser_->factory(); |
6301 auto avfactory = parser_->ast_value_factory(); | 6324 auto avfactory = parser_->ast_value_factory(); |
6302 auto scope = parser_->scope_; | |
6303 auto zone = parser_->zone(); | 6325 auto zone = parser_->zone(); |
6304 Statement* skip = factory->NewEmptyStatement(nopos); | 6326 |
6305 | 6327 |
6306 // let iteratorReturn = iterator.return; | 6328 // let iteratorReturn = iterator.return; |
6307 Variable* var = scope->NewTemporary(avfactory->empty_string()); | 6329 Variable* var_return = var_output; // Reusing the output variable. |
6308 Statement* get_return; | 6330 Statement* get_return; |
6309 { | 6331 { |
6310 Expression* iterator_proxy = factory->NewVariableProxy(iterator); | 6332 Expression* iterator_proxy = factory->NewVariableProxy(iterator); |
6311 Expression* literal = | 6333 Expression* literal = |
6312 factory->NewStringLiteral(avfactory->return_string(), nopos); | 6334 factory->NewStringLiteral(avfactory->return_string(), nopos); |
6313 Expression* property = | 6335 Expression* property = |
6314 factory->NewProperty(iterator_proxy, literal, nopos); | 6336 factory->NewProperty(iterator_proxy, literal, nopos); |
6315 Expression* return_proxy = factory->NewVariableProxy(var); | 6337 Expression* return_proxy = factory->NewVariableProxy(var_return); |
6316 Expression* assignment = factory->NewAssignment( | 6338 Expression* assignment = factory->NewAssignment( |
6317 Token::ASSIGN, return_proxy, property, nopos); | 6339 Token::ASSIGN, return_proxy, property, nopos); |
6318 get_return = factory->NewExpressionStatement(assignment, nopos); | 6340 get_return = factory->NewExpressionStatement(assignment, nopos); |
6319 } | 6341 } |
6320 | 6342 |
6321 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return; OR | 6343 |
6322 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input; | 6344 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|; |
6323 Statement* check_return; | 6345 Statement* check_return; |
6324 { | 6346 { |
6325 Expression* condition = factory->NewCompareOperation( | 6347 Expression* condition = factory->NewCompareOperation( |
6326 Token::EQ, factory->NewVariableProxy(var), | 6348 Token::EQ, factory->NewVariableProxy(var_return), |
6327 factory->NewNullLiteral(nopos), nopos); | 6349 factory->NewNullLiteral(nopos), nopos); |
6328 | 6350 |
6329 Expression* value = input.IsJust() ? | 6351 Expression* value = input.IsJust() ? |
6330 static_cast<Expression*>(factory->NewVariableProxy(input.FromJust())) : | 6352 static_cast<Expression*>(factory->NewVariableProxy(input.FromJust())) : |
6331 factory->NewUndefinedLiteral(nopos); | 6353 factory->NewUndefinedLiteral(nopos); |
6332 | 6354 |
6333 Statement* return_undefined = factory->NewReturnStatement(value, nopos); | 6355 Statement* return_undefined = factory->NewReturnStatement(value, nopos); |
6334 | 6356 |
6335 check_return = | 6357 check_return = factory->NewIfStatement( |
6336 factory->NewIfStatement(condition, return_undefined, skip, nopos); | 6358 condition, return_undefined, factory->NewEmptyStatement(nopos), nopos); |
6337 } | 6359 } |
6338 | 6360 |
6339 // let output = %_Call(iteratorReturn, iterator); OR | 6361 |
6340 // output = %_Call(iteratorReturn, iterator, input); | 6362 // output = %_Call(iteratorReturn, iterator|, input|); |
Dan Ehrenberg
2016/02/16 21:18:30
Not sure why you're passing input to return. This
rossberg
2016/02/17 12:54:45
Fixed.
| |
6341 Statement* call_return; | 6363 Statement* call_return; |
6342 { | 6364 { |
6343 auto args = new (zone) ZoneList<Expression*>(3, zone); | 6365 auto args = new (zone) ZoneList<Expression*>(3, zone); |
6344 args->Add(factory->NewVariableProxy(var), zone); | 6366 args->Add(factory->NewVariableProxy(var_return), zone); |
6345 args->Add(factory->NewVariableProxy(iterator), zone); | 6367 args->Add(factory->NewVariableProxy(iterator), zone); |
6346 if (input.IsJust()) { | 6368 if (input.IsJust()) { |
6347 args->Add(factory->NewVariableProxy(input.FromJust()), zone); | 6369 args->Add(factory->NewVariableProxy(input.FromJust()), zone); |
6348 } | 6370 } |
6349 | 6371 |
6350 Expression* call = | 6372 Expression* call = |
6351 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | 6373 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
6352 Expression* output_proxy = factory->NewVariableProxy( | 6374 Expression* output_proxy = factory->NewVariableProxy(var_output); |
6353 output.IsJust() ? output.FromJust() : var); | |
6354 Expression* assignment = factory->NewAssignment( | 6375 Expression* assignment = factory->NewAssignment( |
6355 Token::ASSIGN, output_proxy, call, nopos); | 6376 Token::ASSIGN, output_proxy, call, nopos); |
6356 call_return = factory->NewExpressionStatement(assignment, nopos); | 6377 call_return = factory->NewExpressionStatement(assignment, nopos); |
6357 } | 6378 } |
6358 | 6379 |
6359 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | 6380 |
6381 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output); | |
6360 Statement* validate_output; | 6382 Statement* validate_output; |
6361 { | 6383 { |
6362 Expression* is_receiver_call; | 6384 Expression* is_receiver_call; |
6363 { | 6385 { |
6364 auto args = new (zone) ZoneList<Expression*>(1, zone); | 6386 auto args = new (zone) ZoneList<Expression*>(1, zone); |
6365 args->Add(factory->NewVariableProxy(var), zone); | 6387 args->Add(factory->NewVariableProxy(var_output), zone); |
6366 is_receiver_call = | 6388 is_receiver_call = |
6367 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | 6389 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); |
6368 } | 6390 } |
6369 | 6391 |
6370 Statement* throw_call; | 6392 Statement* throw_call; |
6371 { | 6393 { |
6372 auto args = new (zone) ZoneList<Expression*>(1, zone); | 6394 auto args = new (zone) ZoneList<Expression*>(1, zone); |
6373 args->Add(factory->NewVariableProxy(var), zone); | 6395 args->Add(factory->NewVariableProxy(var_output), zone); |
6374 Expression* call = factory->NewCallRuntime( | 6396 Expression* call = factory->NewCallRuntime( |
6375 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | 6397 Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
6376 throw_call = factory->NewExpressionStatement(call, nopos); | 6398 throw_call = factory->NewExpressionStatement(call, nopos); |
6377 } | 6399 } |
6378 | 6400 |
6379 validate_output = | 6401 validate_output = factory->NewIfStatement( |
6380 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | 6402 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
6381 } | 6403 } |
6382 | 6404 |
6405 | |
6383 statements->Add(get_return, zone); | 6406 statements->Add(get_return, zone); |
6384 statements->Add(check_return, zone); | 6407 statements->Add(check_return, zone); |
6385 statements->Add(call_return, zone); | 6408 statements->Add(call_return, zone); |
6386 statements->Add(validate_output, zone); | 6409 statements->Add(validate_output, zone); |
6387 } | 6410 } |
6388 | 6411 |
6389 | 6412 |
6413 // Runtime encoding of different completion modes. | |
6414 enum ForOfLoopCompletion { THROW, RETURN_OR_BREAK, NORMAL }; | |
Dan Ehrenberg
2016/02/16 21:18:30
This seems to correspond to JSGeneratorObject::Res
rossberg
2016/02/17 12:54:45
Here it only talks about the completion of the loo
| |
6415 | |
6416 void ParserTraits::BuildIteratorCloseForCompletion( | |
6417 ZoneList<Statement*>* statements, Variable* iterator, | |
6418 Variable* completion) { | |
6419 // | |
6420 // This function adds two statements to [statements], corresponding to the | |
6421 // following code: | |
6422 // | |
6423 // let iteratorReturn = iterator.return; | |
6424 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { | |
6425 // let output; | |
6426 // if (completion === THROW) { | |
6427 // if (!IS_CALLABLE(iteratorReturn)) { | |
6428 // throw MakeTypeError(kReturnMethodNotCallable); | |
6429 // } | |
6430 // try { output = %_Call(iteratorReturn, iterator) } catch (_) { } | |
6431 // } else { | |
6432 // output = %_Call(iteratorReturn, iterator); | |
6433 // } | |
6434 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
6435 // } | |
6436 // | |
6437 | |
6438 const int nopos = RelocInfo::kNoPosition; | |
6439 auto factory = parser_->factory(); | |
6440 auto avfactory = parser_->ast_value_factory(); | |
6441 auto scope = parser_->scope_; | |
6442 auto zone = parser_->zone(); | |
6443 | |
6444 | |
6445 // let output; | |
6446 Variable* var_output = scope->NewTemporary(avfactory->empty_string()); | |
6447 | |
6448 | |
6449 // let iteratorReturn = iterator.return; | |
6450 Variable* var_return = var_output; // Reusing the output variable. | |
6451 Statement* get_return; | |
6452 { | |
6453 Expression* iterator_proxy = factory->NewVariableProxy(iterator); | |
6454 Expression* literal = | |
6455 factory->NewStringLiteral(avfactory->return_string(), nopos); | |
6456 Expression* property = | |
6457 factory->NewProperty(iterator_proxy, literal, nopos); | |
6458 Expression* return_proxy = factory->NewVariableProxy(var_return); | |
6459 Expression* assignment = factory->NewAssignment( | |
6460 Token::ASSIGN, return_proxy, property, nopos); | |
6461 get_return = factory->NewExpressionStatement(assignment, nopos); | |
6462 } | |
6463 | |
6464 | |
6465 // if (!IS_CALLABLE(iteratorReturn)) { | |
6466 // throw MakeTypeError(kReturnMethodNotCallable); | |
6467 // } | |
6468 Statement* check_return_callable; | |
6469 { | |
6470 Expression* type_of = factory->NewUnaryOperation( | |
6471 Token::TYPEOF, factory->NewVariableProxy(var_return), nopos); | |
6472 Expression* function_literal = factory->NewStringLiteral( | |
6473 avfactory->function_string(), nopos); | |
6474 Expression* condition = factory->NewCompareOperation( | |
6475 Token::EQ_STRICT, type_of, function_literal, nopos); | |
Dan Ehrenberg
2016/02/16 21:18:30
FYI mvstanton@: Here's how you can do IsCallable i
mvstanton
2016/02/16 22:55:46
Thanks Dan! Over in my CL I'll put this into a met
rossberg
2016/02/17 12:54:45
Makes sense. Okay, whoever lands second should rem
| |
6476 | |
6477 Expression* call = NewThrowTypeError( | |
6478 MessageTemplate::kReturnMethodNotCallable, | |
6479 avfactory->empty_string(), nopos); | |
6480 Statement* throw_call = factory->NewExpressionStatement(call, nopos); | |
6481 | |
6482 check_return_callable = factory->NewIfStatement( | |
6483 condition, factory->NewEmptyStatement(nopos), throw_call, nopos); | |
6484 } | |
6485 | |
6486 | |
6487 // output = %_Call(iteratorReturn, iterator); | |
6488 Statement* call_return; | |
6489 { | |
6490 auto args = new (zone) ZoneList<Expression*>(2, zone); | |
6491 args->Add(factory->NewVariableProxy(var_return), zone); | |
6492 args->Add(factory->NewVariableProxy(iterator), zone); | |
6493 Expression* call = | |
6494 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | |
6495 | |
6496 Expression* output_proxy = factory->NewVariableProxy(var_output); | |
6497 Expression* assignment = factory->NewAssignment( | |
6498 Token::ASSIGN, output_proxy, call, nopos); | |
6499 call_return = factory->NewExpressionStatement(assignment, nopos); | |
6500 } | |
6501 | |
6502 | |
6503 // try { output = %_Call(iteratorReturn, iterator) } catch (_) { } | |
6504 Statement* try_call_return; | |
6505 { | |
6506 auto args = new (zone) ZoneList<Expression*>(2, zone); | |
6507 args->Add(factory->NewVariableProxy(var_return), zone); | |
6508 args->Add(factory->NewVariableProxy(iterator), zone); | |
6509 | |
6510 Expression* call = | |
6511 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | |
6512 Expression* assignment = factory->NewAssignment( | |
6513 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos); | |
6514 | |
6515 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); | |
6516 try_block->statements()->Add( | |
6517 factory->NewExpressionStatement(assignment, nopos), zone); | |
6518 | |
6519 Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos); | |
6520 | |
6521 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); | |
6522 Variable* catch_variable = catch_scope->DeclareLocal( | |
6523 avfactory->dot_catch_string(), VAR, kCreatedInitialized, | |
6524 Variable::NORMAL); | |
6525 | |
6526 try_call_return = factory->NewTryCatchStatement( | |
6527 try_block, catch_scope, catch_variable, catch_block, nopos); | |
6528 } | |
6529 | |
6530 | |
6531 // if (completion === THROW) { | |
6532 // #check_return_callable; | |
6533 // #try_call_return; | |
6534 // } else { | |
6535 // #call_return; | |
6536 // } | |
6537 Statement* call_return_carefully; | |
6538 { | |
6539 Expression* condition = factory->NewCompareOperation( | |
6540 Token::EQ_STRICT, factory->NewVariableProxy(completion), | |
6541 factory->NewSmiLiteral(THROW, nopos), nopos); | |
6542 | |
6543 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos); | |
6544 then_block->statements()->Add(check_return_callable, zone); | |
6545 then_block->statements()->Add(try_call_return, zone); | |
6546 | |
6547 call_return_carefully = | |
6548 factory->NewIfStatement(condition, then_block, call_return, nopos); | |
6549 } | |
6550 | |
6551 | |
6552 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output); | |
6553 Statement* validate_output; | |
6554 { | |
6555 Expression* is_receiver_call; | |
6556 { | |
6557 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
6558 args->Add(factory->NewVariableProxy(var_output), zone); | |
6559 is_receiver_call = | |
6560 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
6561 } | |
6562 | |
6563 Statement* throw_call; | |
6564 { | |
6565 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
6566 args->Add(factory->NewVariableProxy(var_output), zone); | |
6567 Expression* call = factory->NewCallRuntime( | |
6568 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | |
6569 throw_call = factory->NewExpressionStatement(call, nopos); | |
6570 } | |
6571 | |
6572 validate_output = factory->NewIfStatement( | |
6573 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); | |
6574 } | |
6575 | |
6576 | |
6577 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... } | |
Dan Ehrenberg
2016/02/16 21:18:30
Nit: All your other comments fully say what statem
rossberg
2016/02/17 12:54:45
Actually, not true. The convention (see also Rewri
| |
6578 Statement* maybe_call_return; | |
6579 { | |
6580 Expression* condition = factory->NewCompareOperation( | |
6581 Token::EQ, factory->NewVariableProxy(var_return), | |
6582 factory->NewNullLiteral(nopos), nopos); | |
6583 | |
6584 Block* block = factory->NewBlock(nullptr, 2, false, nopos); | |
6585 block->statements()->Add(call_return_carefully, zone); | |
6586 block->statements()->Add(validate_output, zone); // GAGA | |
Dan Ehrenberg
2016/02/16 21:18:30
GAGA? I don't really see anything funny about this
rossberg
2016/02/17 12:54:45
I missed that one, removed. You'll have to ask Geo
| |
6587 | |
6588 maybe_call_return = factory->NewIfStatement( | |
6589 condition, factory->NewEmptyStatement(nopos), block, nopos); | |
6590 } | |
6591 | |
6592 | |
6593 statements->Add(get_return, zone); | |
6594 statements->Add(maybe_call_return, zone); | |
6595 } | |
6596 | |
6597 | |
6598 Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) { | |
6599 // | |
6600 // This function replaces the loop with the following wrapping: | |
6601 // | |
6602 // let completion = RETURN_OR_BREAK; | |
6603 // try { | |
6604 // #loop; | |
6605 // } catch(e) { | |
6606 // completion = THROW; | |
6607 // throw e; | |
6608 // } finally { | |
6609 // if (!(completion === NORMAL || IS_UNDEFINED(#iterator))) { | |
6610 // #BuildIteratorClose(#iterator, completion) // See above. | |
6611 // } | |
6612 // } | |
6613 // | |
6614 // where the loop's body is wrapped as follows: | |
6615 // | |
6616 // { | |
6617 // {{completion = RETURN_OR_BREAK;}} | |
6618 // #loop-body | |
6619 // {{completion = NORMAL;}} | |
6620 // } | |
6621 | |
6622 const int nopos = RelocInfo::kNoPosition; | |
Dan Ehrenberg
2016/02/16 21:18:30
This desugaring uses nopos for everything. Is that
rossberg
2016/02/17 12:54:45
This is done in various other functions already. I
| |
6623 auto factory = parser_->factory(); | |
6624 auto avfactory = parser_->ast_value_factory(); | |
6625 auto scope = parser_->scope_; | |
6626 auto zone = parser_->zone(); | |
6627 | |
6628 // let completion = RETURN_OR_BREAK; | |
6629 Variable* var_completion = scope->NewTemporary(avfactory->empty_string()); | |
6630 Statement* initialize_completion; | |
6631 { | |
6632 Expression* proxy = factory->NewVariableProxy(var_completion); | |
6633 Expression* assignment = factory->NewAssignment( | |
6634 Token::ASSIGN, proxy, | |
6635 factory->NewSmiLiteral(RETURN_OR_BREAK, nopos), nopos); | |
6636 initialize_completion = | |
6637 factory->NewExpressionStatement(assignment, nopos); | |
6638 } | |
6639 | |
6640 // completion = THROW; | |
6641 Statement* set_completion_throw; | |
6642 { | |
6643 Expression* proxy = factory->NewVariableProxy(var_completion); | |
6644 Expression* assignment = factory->NewAssignment( | |
6645 Token::ASSIGN, proxy, factory->NewSmiLiteral(THROW, nopos), nopos); | |
6646 set_completion_throw = factory->NewExpressionStatement(assignment, nopos); | |
6647 } | |
6648 | |
6649 // if (!(completion === NORMAL || IS_UNDEFINED(#iterator))) { | |
6650 // #BuildIteratorClose(#iterator, completion) | |
6651 // } | |
6652 Block* maybe_close; | |
6653 { | |
6654 Expression* condition1 = factory->NewCompareOperation( | |
6655 Token::EQ_STRICT, factory->NewVariableProxy(var_completion), | |
6656 factory->NewSmiLiteral(NORMAL, nopos), nopos); | |
6657 Expression* condition2 = factory->NewCompareOperation( | |
6658 Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()), | |
6659 factory->NewUndefinedLiteral(nopos), nopos); | |
6660 Expression* condition = factory->NewBinaryOperation( | |
6661 Token::OR, condition1, condition2, nopos); | |
6662 | |
6663 Block* block = factory->NewBlock(nullptr, 2, false, nopos); | |
6664 BuildIteratorClose( | |
6665 block->statements(), loop->iterator(), var_completion); | |
6666 DCHECK(block->statements()->length() == 2); | |
6667 | |
6668 maybe_close = factory->NewBlock(nullptr, 1, false, nopos); | |
6669 maybe_close->statements()->Add(factory->NewIfStatement( | |
6670 condition, factory->NewEmptyStatement(nopos), block, nopos), zone); | |
6671 } | |
6672 | |
6673 // try { #try_block } | |
6674 // catch(e) { | |
6675 // #set_completion_throw; | |
6676 // throw e; | |
6677 // } | |
6678 Statement* try_catch; | |
6679 { | |
6680 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); | |
6681 Variable* catch_variable = catch_scope->DeclareLocal( | |
6682 avfactory->dot_catch_string(), VAR, kCreatedInitialized, | |
6683 Variable::NORMAL); | |
6684 | |
6685 Statement* rethrow; | |
6686 { | |
6687 Expression* proxy = factory->NewVariableProxy(catch_variable); | |
6688 rethrow = factory->NewExpressionStatement( | |
6689 factory->NewThrow(proxy, nopos), nopos); | |
6690 } | |
6691 | |
6692 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); | |
6693 try_block->statements()->Add(loop, zone); | |
6694 | |
6695 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos); | |
6696 catch_block->statements()->Add(set_completion_throw, zone); | |
6697 catch_block->statements()->Add(rethrow, zone); | |
6698 | |
6699 try_catch = factory->NewTryCatchStatement( | |
6700 try_block, catch_scope, catch_variable, catch_block, nopos); | |
6701 } | |
6702 | |
6703 // try { #try_catch } finally { #maybe_close } | |
6704 Statement* try_finally; | |
6705 { | |
6706 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); | |
6707 try_block->statements()->Add(try_catch, zone); | |
6708 | |
6709 try_finally = | |
6710 factory->NewTryFinallyStatement(try_block, maybe_close, nopos); | |
6711 } | |
6712 | |
6713 // #initialize_completion; | |
6714 // #try_finally; | |
6715 Statement* final_loop; | |
6716 { | |
6717 Block* block = factory->NewBlock(nullptr, 2, false, nopos); | |
6718 block->statements()->Add(initialize_completion, zone); | |
6719 block->statements()->Add(try_finally, zone); | |
6720 final_loop = block; | |
6721 } | |
6722 | |
6723 // {{completion = RETURN_OR_BREAK;}} | |
6724 Statement* set_completion_break; | |
6725 { | |
6726 Expression* proxy = factory->NewVariableProxy(var_completion); | |
6727 Expression* assignment = factory->NewAssignment( | |
6728 Token::ASSIGN, proxy, | |
6729 factory->NewSmiLiteral(RETURN_OR_BREAK, nopos), nopos); | |
6730 | |
6731 Block* block = factory->NewBlock(nullptr, 1, true, nopos); | |
6732 block->statements()->Add( | |
6733 factory->NewExpressionStatement(assignment, nopos), zone); | |
6734 set_completion_break = block; | |
6735 } | |
6736 | |
6737 // {{completion = NORMAL;}} | |
6738 Statement* set_completion_normal; | |
6739 { | |
6740 Expression* proxy = factory->NewVariableProxy(var_completion); | |
6741 Expression* assignment = factory->NewAssignment( | |
6742 Token::ASSIGN, proxy, factory->NewSmiLiteral(NORMAL, nopos), nopos); | |
6743 | |
6744 Block* block = factory->NewBlock(nullptr, 1, true, nopos); | |
6745 block->statements()->Add( | |
6746 factory->NewExpressionStatement(assignment, nopos), zone); | |
6747 set_completion_normal = block; | |
6748 } | |
6749 | |
6750 // { #set_completion_break; #loop-body; #set_completion_normal } | |
6751 Block* new_body = factory->NewBlock(nullptr, 2, false, nopos); | |
6752 new_body->statements()->Add(set_completion_break, zone); | |
6753 new_body->statements()->Add(loop->body(), zone); | |
6754 new_body->statements()->Add(set_completion_normal, zone); | |
6755 | |
6756 loop->set_body(new_body); | |
6757 return final_loop; | |
6758 } | |
6759 | |
6760 | |
6390 } // namespace internal | 6761 } // namespace internal |
6391 } // namespace v8 | 6762 } // namespace v8 |
OLD | NEW |