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