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 5779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5790 } else { | 5790 } else { |
5791 DCHECK(value->IsClassLiteral()); | 5791 DCHECK(value->IsClassLiteral()); |
5792 auto class_literal = value->AsClassLiteral(); | 5792 auto class_literal = value->AsClassLiteral(); |
5793 if (class_literal->raw_name() == nullptr) { | 5793 if (class_literal->raw_name() == nullptr) { |
5794 class_literal->set_raw_name(name); | 5794 class_literal->set_raw_name(name); |
5795 } | 5795 } |
5796 } | 5796 } |
5797 } | 5797 } |
5798 | 5798 |
5799 | 5799 |
| 5800 // Desugaring of yield* |
| 5801 // ==================== |
| 5802 // |
| 5803 // With the help of do-expressions and function.sent, we desugar yield* into a |
| 5804 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result |
| 5805 // object around its argument). Concretely, "yield* iterable" turns into |
| 5806 // roughly the following code: |
| 5807 // |
| 5808 // do { |
| 5809 // const kNext = 0; |
| 5810 // const kReturn = 1; |
| 5811 // const kThrow = 2; |
| 5812 // |
| 5813 // let input = function.sent; |
| 5814 // let mode = kNext; |
| 5815 // let output = undefined; |
| 5816 // |
| 5817 // let iterator = iterable[Symbol.iterator](); |
| 5818 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid); |
| 5819 // |
| 5820 // while (true) { |
| 5821 // // From the generator to the iterator: |
| 5822 // // Forward input according to resume mode and obtain output. |
| 5823 // switch (mode) { |
| 5824 // case kNext: |
| 5825 // output = iterator.next(input); |
| 5826 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| 5827 // break; |
| 5828 // case kReturn: |
| 5829 // IteratorClose(iterator, input); // See below. |
| 5830 // break; |
| 5831 // case kThrow: |
| 5832 // let iteratorThrow = iterator.throw; |
| 5833 // if (IS_NULL_OR_UNDEFINED(iteratorThrow)) { |
| 5834 // IteratorClose(iterator); // See below. |
| 5835 // throw MakeTypeError(kThrowMethodMissing); |
| 5836 // } |
| 5837 // output = %_Call(iteratorThrow, iterator, input); |
| 5838 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| 5839 // break; |
| 5840 // } |
| 5841 // if (output.done) break; |
| 5842 // |
| 5843 // // From the generator to its user: |
| 5844 // // Forward output, receive new input, and determine resume mode. |
| 5845 // mode = kReturn; |
| 5846 // try { |
| 5847 // try { |
| 5848 // RawYield(output); // See explanation above. |
| 5849 // mode = kNext; |
| 5850 // } catch (error) { |
| 5851 // mode = kThrow; |
| 5852 // } |
| 5853 // } finally { |
| 5854 // input = function.sent; |
| 5855 // continue; |
| 5856 // } |
| 5857 // } |
| 5858 // |
| 5859 // output.value; |
| 5860 // } |
| 5861 // |
| 5862 // IteratorClose(iterator) expands to the following: |
| 5863 // |
| 5864 // let iteratorReturn = iterator.return; |
| 5865 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return; |
| 5866 // let result = %_Call(iteratorReturn, iterator); |
| 5867 // if (!IS_RECEIVER(result)) %ThrowIterResultNotAnObject(result); |
| 5868 // |
| 5869 // IteratorClose(iterator, input) expands to the following: |
| 5870 // |
| 5871 // let iteratorReturn = iterator.return; |
| 5872 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input; |
| 5873 // let result = %_Call(iteratorReturn, iterator, input); |
| 5874 // if (!IS_RECEIVER(result)) %ThrowIterResultNotAnObject(result); |
| 5875 |
| 5876 |
| 5877 Expression* ParserTraits::RewriteYieldStar( |
| 5878 Expression* generator, Expression* iterable, int pos) { |
| 5879 |
| 5880 const int nopos = RelocInfo::kNoPosition; |
| 5881 |
| 5882 auto factory = parser_->factory(); |
| 5883 auto avfactory = parser_->ast_value_factory(); |
| 5884 auto scope = parser_->scope_; |
| 5885 auto zone = parser_->zone(); |
| 5886 |
| 5887 Statement* skip = factory->NewEmptyStatement(nopos); |
| 5888 |
| 5889 enum { kNext, kReturn, kThrow }; |
| 5890 // TODO(neis): Use JSGenerator::ResumeMode once extended with RETURN. |
| 5891 |
| 5892 // Forward definition for break/continue statements. |
| 5893 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos); |
| 5894 |
| 5895 |
| 5896 // let input = undefined; |
| 5897 Variable* var_input = scope->NewTemporary(avfactory->empty_string()); |
| 5898 Statement* initialize_input; |
| 5899 { |
| 5900 Expression* input_proxy = factory->NewVariableProxy(var_input); |
| 5901 Expression* assignment = factory->NewAssignment( |
| 5902 Token::ASSIGN, input_proxy, factory->NewUndefinedLiteral(nopos), nopos); |
| 5903 initialize_input = factory->NewExpressionStatement(assignment, nopos); |
| 5904 } |
| 5905 |
| 5906 |
| 5907 // let mode = kNext; |
| 5908 Variable* var_mode = scope->NewTemporary(avfactory->empty_string()); |
| 5909 Statement* initialize_mode; |
| 5910 { |
| 5911 Expression* mode_proxy = factory->NewVariableProxy(var_mode); |
| 5912 Expression* knext = factory->NewSmiLiteral(kNext, nopos); |
| 5913 Expression* assignment = |
| 5914 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos); |
| 5915 initialize_mode = factory->NewExpressionStatement(assignment, nopos); |
| 5916 } |
| 5917 |
| 5918 |
| 5919 // let output = undefined; |
| 5920 Variable* var_output = scope->NewTemporary(avfactory->empty_string()); |
| 5921 Statement* initialize_output; |
| 5922 { |
| 5923 Expression* output_proxy = factory->NewVariableProxy(var_output); |
| 5924 Expression* assignment = factory->NewAssignment( |
| 5925 Token::ASSIGN, output_proxy, factory->NewUndefinedLiteral(nopos), |
| 5926 nopos); |
| 5927 initialize_output = factory->NewExpressionStatement(assignment, nopos); |
| 5928 } |
| 5929 |
| 5930 |
| 5931 // let iterator = iterable[Symbol.iterator]; |
| 5932 Variable* var_iterator = scope->NewTemporary(avfactory->empty_string()); |
| 5933 Statement* get_iterator; |
| 5934 { |
| 5935 Expression* iterator = GetIterator(iterable, factory, nopos); |
| 5936 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); |
| 5937 Expression* assignment = factory->NewAssignment( |
| 5938 Token::ASSIGN, iterator_proxy, iterator, nopos); |
| 5939 get_iterator = factory->NewExpressionStatement(assignment, nopos); |
| 5940 } |
| 5941 |
| 5942 |
| 5943 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid); |
| 5944 Statement* validate_iterator; |
| 5945 { |
| 5946 Expression* is_receiver_call; |
| 5947 { |
| 5948 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 5949 args->Add(factory->NewVariableProxy(var_iterator), zone); |
| 5950 is_receiver_call = |
| 5951 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); |
| 5952 } |
| 5953 |
| 5954 Statement* throw_call; |
| 5955 { |
| 5956 Expression* call = NewThrowTypeError( |
| 5957 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(), |
| 5958 nopos); |
| 5959 throw_call = factory->NewExpressionStatement(call, nopos); |
| 5960 } |
| 5961 |
| 5962 validate_iterator = |
| 5963 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| 5964 } |
| 5965 |
| 5966 |
| 5967 // output = iterator.next(input); |
| 5968 Statement* call_next; |
| 5969 { |
| 5970 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); |
| 5971 Expression* literal = |
| 5972 factory->NewStringLiteral(avfactory->next_string(), nopos); |
| 5973 Expression* next_property = |
| 5974 factory->NewProperty(iterator_proxy, literal, nopos); |
| 5975 Expression* input_proxy = factory->NewVariableProxy(var_input); |
| 5976 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 5977 args->Add(input_proxy, zone); |
| 5978 Expression* call = factory->NewCall(next_property, args, nopos); |
| 5979 Expression* output_proxy = factory->NewVariableProxy(var_output); |
| 5980 Expression* assignment = |
| 5981 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos); |
| 5982 call_next = factory->NewExpressionStatement(assignment, nopos); |
| 5983 } |
| 5984 |
| 5985 |
| 5986 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| 5987 Statement* validate_next_output; |
| 5988 { |
| 5989 Expression* is_receiver_call; |
| 5990 { |
| 5991 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 5992 args->Add(factory->NewVariableProxy(var_output), zone); |
| 5993 is_receiver_call = |
| 5994 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); |
| 5995 } |
| 5996 |
| 5997 Statement* throw_call; |
| 5998 { |
| 5999 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 6000 args->Add(factory->NewVariableProxy(var_output), zone); |
| 6001 Expression* call = factory->NewCallRuntime( |
| 6002 Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
| 6003 throw_call = factory->NewExpressionStatement(call, nopos); |
| 6004 } |
| 6005 |
| 6006 validate_next_output = |
| 6007 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| 6008 } |
| 6009 |
| 6010 |
| 6011 // let iteratorThrow = iterator.throw; |
| 6012 Variable* var_throw = scope->NewTemporary(avfactory->empty_string()); |
| 6013 Statement* get_throw; |
| 6014 { |
| 6015 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); |
| 6016 Expression* literal = |
| 6017 factory->NewStringLiteral(avfactory->throw_string(), nopos); |
| 6018 Expression* property = |
| 6019 factory->NewProperty(iterator_proxy, literal, nopos); |
| 6020 Expression* throw_proxy = factory->NewVariableProxy(var_throw); |
| 6021 Expression* assignment = factory->NewAssignment( |
| 6022 Token::ASSIGN, throw_proxy, property, nopos); |
| 6023 get_throw = factory->NewExpressionStatement(assignment, nopos); |
| 6024 } |
| 6025 |
| 6026 |
| 6027 // if (IS_NULL_OR_UNDEFINED(iteratorThrow) { |
| 6028 // IteratorClose(iterator); |
| 6029 // throw MakeTypeError(kThrowMethodMissing); |
| 6030 // } |
| 6031 Statement* check_throw; |
| 6032 { |
| 6033 Expression* condition = factory->NewCompareOperation( |
| 6034 Token::EQ, factory->NewVariableProxy(var_throw), |
| 6035 factory->NewNullLiteral(nopos), nopos); |
| 6036 |
| 6037 Expression* call = NewThrowTypeError( |
| 6038 MessageTemplate::kThrowMethodMissing, |
| 6039 avfactory->empty_string(), nopos); |
| 6040 Statement* throw_call = factory->NewExpressionStatement(call, nopos); |
| 6041 |
| 6042 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); |
| 6043 BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>()); |
| 6044 then->statements()->Add(throw_call, zone); |
| 6045 check_throw = |
| 6046 factory->NewIfStatement(condition, then, skip, nopos); |
| 6047 } |
| 6048 |
| 6049 |
| 6050 // output = %_Call(iteratorThrow, iterator, input); |
| 6051 Statement* call_throw; |
| 6052 { |
| 6053 auto args = new (zone) ZoneList<Expression*>(3, zone); |
| 6054 args->Add(factory->NewVariableProxy(var_throw), zone); |
| 6055 args->Add(factory->NewVariableProxy(var_iterator), zone); |
| 6056 args->Add(factory->NewVariableProxy(var_input), zone); |
| 6057 Expression* call = |
| 6058 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
| 6059 Expression* assignment = factory->NewAssignment( |
| 6060 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos); |
| 6061 call_throw = factory->NewExpressionStatement(assignment, nopos); |
| 6062 } |
| 6063 |
| 6064 |
| 6065 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| 6066 Statement* validate_throw_output; |
| 6067 { |
| 6068 Expression* is_receiver_call; |
| 6069 { |
| 6070 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 6071 args->Add(factory->NewVariableProxy(var_output), zone); |
| 6072 is_receiver_call = |
| 6073 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); |
| 6074 } |
| 6075 |
| 6076 Statement* throw_call; |
| 6077 { |
| 6078 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 6079 args->Add(factory->NewVariableProxy(var_output), zone); |
| 6080 Expression* call = factory->NewCallRuntime( |
| 6081 Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
| 6082 throw_call = factory->NewExpressionStatement(call, nopos); |
| 6083 } |
| 6084 |
| 6085 validate_throw_output = |
| 6086 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| 6087 } |
| 6088 |
| 6089 |
| 6090 // if (output.done) break; |
| 6091 Statement* if_done; |
| 6092 { |
| 6093 Expression* output_proxy = factory->NewVariableProxy(var_output); |
| 6094 Expression* literal = |
| 6095 factory->NewStringLiteral(avfactory->done_string(), nopos); |
| 6096 Expression* property = factory->NewProperty(output_proxy, literal, nopos); |
| 6097 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos); |
| 6098 if_done = factory->NewIfStatement(property, break_loop, skip, nopos); |
| 6099 } |
| 6100 |
| 6101 |
| 6102 // mode = kReturn; |
| 6103 Statement* set_mode_return; |
| 6104 { |
| 6105 Expression* mode_proxy = factory->NewVariableProxy(var_mode); |
| 6106 Expression* kreturn = factory->NewSmiLiteral(kReturn, nopos); |
| 6107 Expression* assignment = |
| 6108 factory->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos); |
| 6109 set_mode_return = factory->NewExpressionStatement(assignment, nopos); |
| 6110 } |
| 6111 |
| 6112 |
| 6113 // RawYield(output); |
| 6114 Statement* yield_output; |
| 6115 { |
| 6116 Expression* output_proxy = factory->NewVariableProxy(var_output); |
| 6117 Yield* yield = factory->NewYield( |
| 6118 generator, output_proxy, Yield::kInitial, nopos); |
| 6119 yield_output = factory->NewExpressionStatement(yield, nopos); |
| 6120 } |
| 6121 |
| 6122 |
| 6123 // mode = kNext; |
| 6124 Statement* set_mode_next; |
| 6125 { |
| 6126 Expression* mode_proxy = factory->NewVariableProxy(var_mode); |
| 6127 Expression* knext = factory->NewSmiLiteral(kNext, nopos); |
| 6128 Expression* assignment = |
| 6129 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos); |
| 6130 set_mode_next = factory->NewExpressionStatement(assignment, nopos); |
| 6131 } |
| 6132 |
| 6133 |
| 6134 // mode = kThrow; |
| 6135 Statement* set_mode_throw; |
| 6136 { |
| 6137 Expression* mode_proxy = factory->NewVariableProxy(var_mode); |
| 6138 Expression* kthrow = factory->NewSmiLiteral(kThrow, nopos); |
| 6139 Expression* assignment = |
| 6140 factory->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos); |
| 6141 set_mode_throw = factory->NewExpressionStatement(assignment, nopos); |
| 6142 } |
| 6143 |
| 6144 |
| 6145 // input = function.sent; |
| 6146 Statement* get_input; |
| 6147 { |
| 6148 Expression* function_sent = FunctionSentExpression(scope, factory, nopos); |
| 6149 Expression* input_proxy = factory->NewVariableProxy(var_input); |
| 6150 Expression* assignment = factory->NewAssignment( |
| 6151 Token::ASSIGN, input_proxy, function_sent, nopos); |
| 6152 get_input = factory->NewExpressionStatement(assignment, nopos); |
| 6153 } |
| 6154 |
| 6155 |
| 6156 // output.value; |
| 6157 Statement* get_value; |
| 6158 { |
| 6159 Expression* output_proxy = factory->NewVariableProxy(var_output); |
| 6160 Expression* literal = |
| 6161 factory->NewStringLiteral(avfactory->value_string(), nopos); |
| 6162 Expression* property = factory->NewProperty(output_proxy, literal, nopos); |
| 6163 get_value = factory->NewExpressionStatement(property, nopos); |
| 6164 } |
| 6165 |
| 6166 |
| 6167 // Now put things together. |
| 6168 |
| 6169 |
| 6170 // try { ... } catch(e) { ... } |
| 6171 Statement* try_catch; |
| 6172 { |
| 6173 Block* try_block = factory->NewBlock(nullptr, 2, false, nopos); |
| 6174 try_block->statements()->Add(yield_output, zone); |
| 6175 try_block->statements()->Add(set_mode_next, zone); |
| 6176 |
| 6177 Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos); |
| 6178 catch_block->statements()->Add(set_mode_throw, zone); |
| 6179 |
| 6180 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); |
| 6181 const AstRawString* name = avfactory->dot_catch_string(); |
| 6182 Variable* catch_variable = |
| 6183 catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, |
| 6184 Variable::NORMAL); |
| 6185 |
| 6186 try_catch = factory->NewTryCatchStatement( |
| 6187 try_block, catch_scope, catch_variable, catch_block, nopos); |
| 6188 } |
| 6189 |
| 6190 |
| 6191 // try { ... } finally { ... } |
| 6192 Statement* try_finally; |
| 6193 { |
| 6194 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); |
| 6195 try_block->statements()->Add(try_catch, zone); |
| 6196 |
| 6197 Block* finally = factory->NewBlock(nullptr, 2, false, nopos); |
| 6198 finally->statements()->Add(get_input, zone); |
| 6199 finally->statements()->Add( |
| 6200 factory->NewContinueStatement(loop, nopos), zone); |
| 6201 |
| 6202 try_finally = factory->NewTryFinallyStatement(try_block, finally, nopos); |
| 6203 } |
| 6204 |
| 6205 |
| 6206 // switch (mode) { ... } |
| 6207 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos); |
| 6208 { |
| 6209 auto case_next = new (zone) ZoneList<Statement*>(3, zone); |
| 6210 case_next->Add(call_next, zone); |
| 6211 case_next->Add(validate_next_output, zone); |
| 6212 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| 6213 |
| 6214 auto case_return = new (zone) ZoneList<Statement*>(5, zone); |
| 6215 BuildIteratorClose(case_return, var_iterator, Just(var_input)); |
| 6216 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| 6217 |
| 6218 auto case_throw = new (zone) ZoneList<Statement*>(5, zone); |
| 6219 case_throw->Add(get_throw, zone); |
| 6220 case_throw->Add(check_throw, zone); |
| 6221 case_throw->Add(call_throw, zone); |
| 6222 case_throw->Add(validate_throw_output, zone); |
| 6223 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| 6224 |
| 6225 auto cases = new (zone) ZoneList<CaseClause*>(3, zone); |
| 6226 Expression* knext = factory->NewSmiLiteral(kNext, nopos); |
| 6227 Expression* kreturn = factory->NewSmiLiteral(kReturn, nopos); |
| 6228 Expression* kthrow = factory->NewSmiLiteral(kThrow, nopos); |
| 6229 cases->Add(factory->NewCaseClause(knext, case_next, nopos), zone); |
| 6230 cases->Add(factory->NewCaseClause(kreturn, case_return, nopos), zone); |
| 6231 cases->Add(factory->NewCaseClause(kthrow, case_throw, nopos), zone); |
| 6232 |
| 6233 switch_mode->Initialize(factory->NewVariableProxy(var_mode), cases); |
| 6234 } |
| 6235 |
| 6236 |
| 6237 // while (true) { ... } |
| 6238 // Already defined earlier: WhileStatement* loop = ... |
| 6239 { |
| 6240 Block* loop_body = factory->NewBlock(nullptr, 4, false, nopos); |
| 6241 loop_body->statements()->Add(switch_mode, zone); |
| 6242 loop_body->statements()->Add(if_done, zone); |
| 6243 loop_body->statements()->Add(set_mode_return, zone); |
| 6244 loop_body->statements()->Add(try_finally, zone); |
| 6245 |
| 6246 loop->Initialize(factory->NewBooleanLiteral(true, nopos), loop_body); |
| 6247 } |
| 6248 |
| 6249 |
| 6250 // do { ... } |
| 6251 DoExpression* yield_star; |
| 6252 { |
| 6253 // The rewriter needs to process the get_value statement only, hence we |
| 6254 // put the preceding statements into an init block. |
| 6255 |
| 6256 Block* do_block_ = factory->NewBlock(nullptr, 6, true, nopos); |
| 6257 do_block_->statements()->Add(initialize_input, zone); |
| 6258 do_block_->statements()->Add(initialize_mode, zone); |
| 6259 do_block_->statements()->Add(initialize_output, zone); |
| 6260 do_block_->statements()->Add(get_iterator, zone); |
| 6261 do_block_->statements()->Add(validate_iterator, zone); |
| 6262 do_block_->statements()->Add(loop, zone); |
| 6263 |
| 6264 Block* do_block = factory->NewBlock(nullptr, 2, false, nopos); |
| 6265 do_block->statements()->Add(do_block_, zone); |
| 6266 do_block->statements()->Add(get_value, zone); |
| 6267 |
| 6268 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); |
| 6269 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); |
| 6270 Rewriter::Rewrite(parser_, yield_star, avfactory); |
| 6271 } |
| 6272 |
| 6273 return yield_star; |
| 6274 } |
| 6275 |
| 6276 |
| 6277 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| 6278 Variable* iterator, |
| 6279 Maybe<Variable*> input) { |
| 6280 const int nopos = RelocInfo::kNoPosition; |
| 6281 auto factory = parser_->factory(); |
| 6282 auto avfactory = parser_->ast_value_factory(); |
| 6283 auto scope = parser_->scope_; |
| 6284 auto zone = parser_->zone(); |
| 6285 Statement* skip = factory->NewEmptyStatement(nopos); |
| 6286 |
| 6287 // let iteratorReturn = iterator.return; |
| 6288 Variable* var = scope->NewTemporary(avfactory->empty_string()); |
| 6289 Statement* get_return; |
| 6290 { |
| 6291 Expression* iterator_proxy = factory->NewVariableProxy(iterator); |
| 6292 Expression* literal = |
| 6293 factory->NewStringLiteral(avfactory->return_string(), nopos); |
| 6294 Expression* property = |
| 6295 factory->NewProperty(iterator_proxy, literal, nopos); |
| 6296 Expression* return_proxy = factory->NewVariableProxy(var); |
| 6297 Expression* assignment = factory->NewAssignment( |
| 6298 Token::ASSIGN, return_proxy, property, nopos); |
| 6299 get_return = factory->NewExpressionStatement(assignment, nopos); |
| 6300 } |
| 6301 |
| 6302 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return; OR |
| 6303 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input; |
| 6304 Statement* check_return; |
| 6305 { |
| 6306 Expression* condition = factory->NewCompareOperation( |
| 6307 Token::EQ, factory->NewVariableProxy(var), |
| 6308 factory->NewNullLiteral(nopos), nopos); |
| 6309 |
| 6310 Expression* value = input.IsJust() ? |
| 6311 static_cast<Expression*>(factory->NewVariableProxy(input.FromJust())) : |
| 6312 factory->NewUndefinedLiteral(nopos); |
| 6313 |
| 6314 Statement* return_undefined = factory->NewReturnStatement(value, nopos); |
| 6315 |
| 6316 check_return = |
| 6317 factory->NewIfStatement(condition, return_undefined, skip, nopos); |
| 6318 } |
| 6319 |
| 6320 // let result = %_Call(iteratorReturn, iterator); OR |
| 6321 // let result = %_Call(iteratorReturn, iterator, input); |
| 6322 Statement* call_return; |
| 6323 { |
| 6324 auto args = new (zone) ZoneList<Expression*>(3, zone); |
| 6325 args->Add(factory->NewVariableProxy(var), zone); |
| 6326 args->Add(factory->NewVariableProxy(iterator), zone); |
| 6327 if (input.IsJust()) { |
| 6328 args->Add(factory->NewVariableProxy(input.FromJust()), zone); |
| 6329 } |
| 6330 |
| 6331 Expression* call = |
| 6332 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
| 6333 Expression* assignment = factory->NewAssignment( |
| 6334 Token::ASSIGN, factory->NewVariableProxy(var), call, nopos); |
| 6335 call_return = factory->NewExpressionStatement(assignment, nopos); |
| 6336 } |
| 6337 |
| 6338 // if (!IS_RECEIVER(result)) %ThrowIterResultNotAnObject(result); |
| 6339 Statement* validate_result; |
| 6340 { |
| 6341 Expression* is_receiver_call; |
| 6342 { |
| 6343 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 6344 args->Add(factory->NewVariableProxy(var), zone); |
| 6345 is_receiver_call = |
| 6346 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); |
| 6347 } |
| 6348 |
| 6349 Statement* throw_call; |
| 6350 { |
| 6351 auto args = new (zone) ZoneList<Expression*>(1, zone); |
| 6352 args->Add(factory->NewVariableProxy(var), zone); |
| 6353 Expression* call = factory->NewCallRuntime( |
| 6354 Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
| 6355 throw_call = factory->NewExpressionStatement(call, nopos); |
| 6356 } |
| 6357 |
| 6358 validate_result = |
| 6359 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| 6360 } |
| 6361 |
| 6362 statements->Add(get_return, zone); |
| 6363 statements->Add(check_return, zone); |
| 6364 statements->Add(call_return, zone); |
| 6365 statements->Add(validate_result, zone); |
| 6366 } |
| 6367 |
| 6368 |
5800 } // namespace internal | 6369 } // namespace internal |
5801 } // namespace v8 | 6370 } // namespace v8 |
OLD | NEW |