Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: src/parsing/parser.cc

Issue 1643903003: [generators] Desugar yield*. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 an "raw" yield (a yield that doesn't wrap its argument).
rossberg 2016/01/29 18:12:27 Nit: s/an/a/
5805 // Concretely, "yield* iterable" turns into roughly the following code:
5806 //
5807 // do {
5808 // const kNext = 0;
5809 // const kReturn = 1;
5810 // const kThrow = 2;
5811 //
5812 // let input = function.sent;
5813 // let mode = kNext;
5814 // let output = undefined;
5815 //
5816 // let iterator = iterable[Symbol.iterator]();
5817 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
5818 //
5819 // while (true) {
5820 // // From the generator to the iterator:
5821 // // Forward input according to resume mode and obtain output.
5822 // switch (mode) {
5823 // case kNext:
5824 // output = iterator.next(input);
5825 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5826 // break;
5827 // case kReturn:
5828 // let iteratorReturn = iterator.return;
5829 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
5830 // output = %_Call(iteratorReturn, iterator, input);
5831 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5832 // break;
5833 // case kThrow:
5834 // let iteratorThrow = iterator.throw;
5835 // if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
rossberg 2016/01/29 18:12:27 Hm, this logic is so random. Why close the iterato
5836 // IteratorClose(iterator);
5837 // throw MakeTypeError(kThrowMethodMissing);
5838 // }
5839 // output = %_Call(iteratorThrow, iterator, input);
5840 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5841 // break;
5842 // }
5843 // if (output.done) break;
5844 //
5845 // // From the generator to its user:
5846 // // Forward output, receive new input, and determine resume mode.
5847 // mode = kReturn;
5848 // try {
5849 // try {
5850 // RawYield(output);
rossberg 2016/01/29 18:12:27 What's RawYield?
neis 2016/01/31 19:21:49 It's explained in the comment above.
5851 // mode = kNext;
5852 // } catch (error) {
5853 // mode = kThrow;
5854 // }
5855 // } finally {
5856 // input = function.sent;
5857 // continue;
5858 // }
5859 // }
5860 //
5861 // output.value;
5862 // }
5863 //
5864 // IteratorClose(iterator) in the code above expands to the following:
5865 //
5866 // let iteratorReturn = iterator.return;
5867 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return;
5868 // let result = %_Call(iteratorReturn, iterator);
5869 // if (!IS_RECEIVER(result)) throw MakeTypeError(kIllegalInvocation);
5870
5871
5872 Expression* ParserTraits::RewriteYieldStar(
5873 Expression* generator, Expression* iterable, int pos) {
5874
5875 const int nopos = RelocInfo::kNoPosition;
5876
5877 auto factory = parser_->factory();
5878 auto avfactory = parser_->ast_value_factory();
5879 auto scope = parser_->scope_;
5880 auto zone = parser_->zone();
5881
5882 Statement* skip = factory->NewEmptyStatement(nopos);
5883
5884 enum { kNext, kReturn, kThrow };
5885
5886 // Forward definition for break/continue statements.
5887 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos);
5888
5889
5890 // let input = undefined;
5891 Variable* var_input = scope->NewTemporary(avfactory->empty_string());
5892 Statement* initialize_input;
5893 {
5894 Expression* input_proxy = factory->NewVariableProxy(var_input);
5895 Expression* assignment = factory->NewAssignment(
5896 Token::ASSIGN, input_proxy, factory->NewUndefinedLiteral(nopos), nopos);
5897 initialize_input = factory->NewExpressionStatement(assignment, nopos);
5898 }
5899
5900
5901 // let mode = kNext;
5902 Variable* var_mode = scope->NewTemporary(avfactory->empty_string());
5903 Statement* initialize_mode;
5904 {
5905 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
5906 Expression* knext = factory->NewSmiLiteral(kNext, nopos);
5907 Expression* assignment =
5908 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
5909 initialize_mode = factory->NewExpressionStatement(assignment, nopos);
5910 }
5911
5912
5913 // let output = undefined;
5914 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
5915 Statement* initialize_output;
5916 {
5917 Expression* output_proxy = factory->NewVariableProxy(var_output);
5918 Expression* assignment = factory->NewAssignment(
5919 Token::ASSIGN, output_proxy, factory->NewUndefinedLiteral(nopos),
5920 nopos);
5921 initialize_output = factory->NewExpressionStatement(assignment, nopos);
5922 }
5923
5924
5925 // let iterator = iterable[Symbol.iterator];
5926 Variable* var_iterator = scope->NewTemporary(avfactory->empty_string());
5927 Statement* get_iterator;
5928 {
5929 Expression* iterator = GetIterator(iterable, factory, nopos);
5930 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5931 Expression* assignment = factory->NewAssignment(
5932 Token::ASSIGN, iterator_proxy, iterator, nopos);
5933 get_iterator = factory->NewExpressionStatement(assignment, nopos);
5934 }
5935
5936
5937 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
5938 Statement* validate_iterator;
5939 {
5940 Expression* is_receiver_call;
5941 {
5942 auto args = new (zone) ZoneList<Expression*>(1, zone);
5943 args->Add(factory->NewVariableProxy(var_iterator), zone);
5944 is_receiver_call =
5945 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5946 }
5947
5948 Statement* throw_call;
5949 {
5950 Expression* call = NewThrowTypeError(
5951 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(),
5952 nopos);
5953 throw_call = factory->NewExpressionStatement(call, nopos);
5954 }
5955
5956 validate_iterator =
5957 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos);
5958 }
5959
5960
5961 // output = iterator.next(input);
5962 Statement* call_next;
5963 {
5964 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5965 Expression* literal =
5966 factory->NewStringLiteral(avfactory->next_string(), nopos);
5967 Expression* next_property =
5968 factory->NewProperty(iterator_proxy, literal, nopos);
5969 Expression* input_proxy = factory->NewVariableProxy(var_input);
5970 auto args = new (zone) ZoneList<Expression*>(1, zone);
5971 args->Add(input_proxy, zone);
5972 Expression* call = factory->NewCall(next_property, args, nopos);
5973 Expression* output_proxy = factory->NewVariableProxy(var_output);
5974 Expression* assignment =
5975 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
5976 call_next = factory->NewExpressionStatement(assignment, nopos);
5977 }
5978
5979
5980 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5981 Statement* validate_next_output;
5982 {
5983 Expression* is_receiver_call;
5984 {
5985 auto args = new (zone) ZoneList<Expression*>(1, zone);
5986 args->Add(factory->NewVariableProxy(var_output), zone);
5987 is_receiver_call =
5988 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5989 }
5990
5991 Statement* throw_call;
5992 {
5993 auto args = new (zone) ZoneList<Expression*>(1, zone);
5994 args->Add(factory->NewVariableProxy(var_output), zone);
5995 Expression* call = factory->NewCallRuntime(
5996 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
5997 throw_call = factory->NewExpressionStatement(call, nopos);
5998 }
5999
6000 validate_next_output =
6001 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos);
6002 }
6003
6004
6005 // let iteratorReturn = iterator.return;
6006 Variable* var_return = scope->NewTemporary(avfactory->empty_string());
rossberg 2016/01/29 18:12:27 Nit: I suppose you could reuse some of the tempora
neis 2016/01/31 19:21:49 You mean e.g. merge var_return, var_throw, var_nex
6007 Statement* get_return;
6008 {
6009 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
6010 Expression* literal =
6011 factory->NewStringLiteral(avfactory->return_string(), nopos);
6012 Expression* property =
6013 factory->NewProperty(iterator_proxy, literal, nopos);
6014 Expression* return_proxy = factory->NewVariableProxy(var_return);
6015 Expression* assignment = factory->NewAssignment(
6016 Token::ASSIGN, return_proxy, property, nopos);
6017 get_return = factory->NewExpressionStatement(assignment, nopos);
6018 }
6019
6020
6021 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input;
6022 Statement* check_return;
6023 {
6024 Expression* condition = factory->NewCompareOperation(
6025 Token::EQ, factory->NewVariableProxy(var_return),
6026 factory->NewNullLiteral(nopos), nopos);
6027 Statement* return_input = factory->NewReturnStatement(
6028 factory->NewVariableProxy(var_input), nopos);
6029 check_return =
6030 factory->NewIfStatement(condition, return_input, skip, nopos);
6031 }
6032
6033
6034 // output = %_Call(iteratorReturn, iterator, input);
6035 Statement* call_return;
6036 {
6037 auto args = new (zone) ZoneList<Expression*>(3, zone);
6038 args->Add(factory->NewVariableProxy(var_return), zone);
6039 args->Add(factory->NewVariableProxy(var_iterator), zone);
6040 args->Add(factory->NewVariableProxy(var_input), zone);
6041 Expression* call =
6042 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6043 Expression* assignment = factory->NewAssignment(
6044 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
6045 call_return = factory->NewExpressionStatement(assignment, nopos);
6046 }
6047
6048
6049 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6050 Statement* validate_return_output;
6051 {
6052 Expression* is_receiver_call;
6053 {
6054 auto args = new (zone) ZoneList<Expression*>(1, zone);
6055 args->Add(factory->NewVariableProxy(var_output), zone);
6056 is_receiver_call =
6057 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6058 }
6059
6060 Statement* throw_call;
6061 {
6062 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone);
6063 args->Add(factory->NewVariableProxy(var_output), zone);
6064 Expression* call = factory->NewCallRuntime(
6065 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6066 throw_call = factory->NewExpressionStatement(call, nopos);
6067 }
6068
6069 validate_return_output =
6070 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos);
6071 }
6072
6073
6074 // let iteratorThrow = iterator.throw;
6075 Variable* var_throw = scope->NewTemporary(avfactory->empty_string());
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_throw);
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_throw),
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_throw), 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 // TODO(neis): Having an init block here is a temporary hack to avoid
6320 // crashing the rewriter.
neis 2016/01/28 11:15:13 When just using one normal block, the rewriter cra
rossberg 2016/01/29 18:12:27 Is there a bug for that?
neis 2016/01/31 19:21:49 I didn't check. I wasn't sure if it's the rewrite
6321 Block* do_block = factory->NewBlock(nullptr, 6, true, nopos);
6322 do_block->statements()->Add(initialize_input, zone);
6323 do_block->statements()->Add(initialize_mode, zone);
6324 do_block->statements()->Add(initialize_output, zone);
6325 do_block->statements()->Add(get_iterator, zone);
6326 do_block->statements()->Add(validate_iterator, zone);
6327 do_block->statements()->Add(loop, zone);
6328
6329 Block* do_block_ = factory->NewBlock(nullptr, 2, false, nopos);
6330 do_block_->statements()->Add(do_block, zone);
6331 do_block_->statements()->Add(get_value, zone);
6332
6333 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
6334 yield_star = factory->NewDoExpression(do_block_, dot_result, nopos);
6335 Rewriter::Rewrite(parser_, yield_star, avfactory);
6336 }
6337
6338 return yield_star;
6339 }
adamk 2016/02/01 21:38:42 This function is almost 500 lines long. Should we
6340
6341
6342 void ParserTraits::BuildIteratorClose(
6343 ZoneList<Statement*>* statements, Variable* iterator) {
6344
6345 const int nopos = RelocInfo::kNoPosition;
6346 auto factory = parser_->factory();
6347 auto avfactory = parser_->ast_value_factory();
6348 auto scope = parser_->scope_;
6349 auto zone = parser_->zone();
6350 Statement* skip = factory->NewEmptyStatement(nopos);
6351
6352 // let iteratorReturn = iterator.return;
6353 Variable* var_return = scope->NewTemporary(avfactory->empty_string());
6354 Statement* get_return;
6355 {
6356 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6357 Expression* literal =
6358 factory->NewStringLiteral(avfactory->return_string(), nopos);
6359 Expression* property =
6360 factory->NewProperty(iterator_proxy, literal, nopos);
6361 Expression* return_proxy = factory->NewVariableProxy(var_return);
6362 Expression* assignment = factory->NewAssignment(
6363 Token::ASSIGN, return_proxy, property, nopos);
6364 get_return = factory->NewExpressionStatement(assignment, nopos);
6365 }
6366
6367 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return;
6368 Statement* check_return;
6369 {
6370 Expression* condition = factory->NewCompareOperation(
6371 Token::EQ, factory->NewVariableProxy(var_return),
6372 factory->NewNullLiteral(nopos), nopos);
6373
6374 Statement* return_undefined = factory->NewReturnStatement(
6375 factory->NewUndefinedLiteral(nopos), nopos);
6376
6377 check_return =
6378 factory->NewIfStatement(condition, return_undefined, skip, nopos);
6379 }
6380
6381 // let result = %_Call(iteratorReturn, iterator);
6382 Variable* var_result = scope->NewTemporary(avfactory->empty_string());
6383 Statement* call_return;
6384 {
6385 auto args = new (zone) ZoneList<Expression*>(2, zone);
6386 args->Add(factory->NewVariableProxy(var_return), 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_result), 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_result), 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_result), 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698