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 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 |
OLD | NEW |