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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 4291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4302 const auto& assignments = | 4302 const auto& assignments = |
4303 function_state_->destructuring_assignments_to_rewrite(); | 4303 function_state_->destructuring_assignments_to_rewrite(); |
4304 for (int i = assignments.length() - 1; i >= 0; --i) { | 4304 for (int i = assignments.length() - 1; i >= 0; --i) { |
4305 // Rewrite list in reverse, so that nested assignment patterns are rewritten | 4305 // Rewrite list in reverse, so that nested assignment patterns are rewritten |
4306 // correctly. | 4306 // correctly. |
4307 const DestructuringAssignment& pair = assignments.at(i); | 4307 const DestructuringAssignment& pair = assignments.at(i); |
4308 RewritableExpression* to_rewrite = | 4308 RewritableExpression* to_rewrite = |
4309 pair.assignment->AsRewritableExpression(); | 4309 pair.assignment->AsRewritableExpression(); |
4310 DCHECK_NOT_NULL(to_rewrite); | 4310 DCHECK_NOT_NULL(to_rewrite); |
4311 if (!to_rewrite->is_rewritten()) { | 4311 if (!to_rewrite->is_rewritten()) { |
4312 // Since this function is called at the end of parsing the program, | 4312 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, |
4313 // pair.scope may already have been removed by FinalizeBlockScope in the | 4313 pair.scope); |
4314 // meantime. | |
4315 Scope* scope = pair.scope->GetUnremovedScope(); | |
4316 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); | |
4317 } | 4314 } |
4318 } | 4315 } |
4319 } | 4316 } |
4320 | 4317 |
4321 Expression* Parser::RewriteExponentiation(Expression* left, Expression* right, | 4318 Expression* Parser::RewriteExponentiation(Expression* left, Expression* right, |
4322 int pos) { | 4319 int pos) { |
4323 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | 4320 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
4324 args->Add(left, zone()); | 4321 args->Add(left, zone()); |
4325 args->Add(right, zone()); | 4322 args->Add(right, zone()); |
4326 return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos); | 4323 return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos); |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4741 Expression* condition = factory()->NewCompareOperation( | 4738 Expression* condition = factory()->NewCompareOperation( |
4742 Token::EQ, factory()->NewVariableProxy(var_throw), | 4739 Token::EQ, factory()->NewVariableProxy(var_throw), |
4743 factory()->NewNullLiteral(nopos), nopos); | 4740 factory()->NewNullLiteral(nopos), nopos); |
4744 Expression* call = | 4741 Expression* call = |
4745 NewThrowTypeError(MessageTemplate::kThrowMethodMissing, | 4742 NewThrowTypeError(MessageTemplate::kThrowMethodMissing, |
4746 ast_value_factory()->empty_string(), nopos); | 4743 ast_value_factory()->empty_string(), nopos); |
4747 Statement* throw_call = factory()->NewExpressionStatement(call, nopos); | 4744 Statement* throw_call = factory()->NewExpressionStatement(call, nopos); |
4748 | 4745 |
4749 Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos); | 4746 Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos); |
4750 BuildIteratorCloseForCompletion( | 4747 BuildIteratorCloseForCompletion( |
4751 scope(), then->statements(), var_iterator, | 4748 then->statements(), var_iterator, |
4752 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos)); | 4749 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos)); |
4753 then->statements()->Add(throw_call, zone()); | 4750 then->statements()->Add(throw_call, zone()); |
4754 check_throw = factory()->NewIfStatement( | 4751 check_throw = factory()->NewIfStatement( |
4755 condition, then, factory()->NewEmptyStatement(nopos), nopos); | 4752 condition, then, factory()->NewEmptyStatement(nopos), nopos); |
4756 } | 4753 } |
4757 | 4754 |
4758 // output = %_Call(iteratorThrow, iterator, input); | 4755 // output = %_Call(iteratorThrow, iterator, input); |
4759 Statement* call_throw; | 4756 Statement* call_throw; |
4760 { | 4757 { |
4761 auto args = new (zone()) ZoneList<Expression*>(3, zone()); | 4758 auto args = new (zone()) ZoneList<Expression*>(3, zone()); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5109 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, | 5106 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, |
5110 nopos); | 5107 nopos); |
5111 } | 5108 } |
5112 | 5109 |
5113 statements->Add(get_return, zone()); | 5110 statements->Add(get_return, zone()); |
5114 statements->Add(check_return, zone()); | 5111 statements->Add(check_return, zone()); |
5115 statements->Add(call_return, zone()); | 5112 statements->Add(call_return, zone()); |
5116 statements->Add(validate_output, zone()); | 5113 statements->Add(validate_output, zone()); |
5117 } | 5114 } |
5118 | 5115 |
5119 void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, | 5116 void Parser::FinalizeIteratorUse(Variable* completion, Expression* condition, |
5120 Expression* condition, Variable* iter, | 5117 Variable* iter, Block* iterator_use, |
5121 Block* iterator_use, Block* target) { | 5118 Block* target) { |
5122 // | 5119 // |
5123 // This function adds two statements to [target], corresponding to the | 5120 // This function adds two statements to [target], corresponding to the |
5124 // following code: | 5121 // following code: |
5125 // | 5122 // |
5126 // completion = kNormalCompletion; | 5123 // completion = kNormalCompletion; |
5127 // try { | 5124 // try { |
5128 // try { | 5125 // try { |
5129 // iterator_use | 5126 // iterator_use |
5130 // } catch(e) { | 5127 // } catch(e) { |
5131 // if (completion === kAbruptCompletion) completion = kThrowCompletion; | 5128 // if (completion === kAbruptCompletion) completion = kThrowCompletion; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5167 condition, statement, factory()->NewEmptyStatement(nopos), nopos); | 5164 condition, statement, factory()->NewEmptyStatement(nopos), nopos); |
5168 } | 5165 } |
5169 | 5166 |
5170 // if (condition) { | 5167 // if (condition) { |
5171 // #BuildIteratorCloseForCompletion(iter, completion) | 5168 // #BuildIteratorCloseForCompletion(iter, completion) |
5172 // } | 5169 // } |
5173 Block* maybe_close; | 5170 Block* maybe_close; |
5174 { | 5171 { |
5175 Block* block = factory()->NewBlock(nullptr, 2, true, nopos); | 5172 Block* block = factory()->NewBlock(nullptr, 2, true, nopos); |
5176 Expression* proxy = factory()->NewVariableProxy(completion); | 5173 Expression* proxy = factory()->NewVariableProxy(completion); |
5177 BuildIteratorCloseForCompletion(use_scope, block->statements(), iter, | 5174 BuildIteratorCloseForCompletion(block->statements(), iter, proxy); |
5178 proxy); | |
5179 DCHECK(block->statements()->length() == 2); | 5175 DCHECK(block->statements()->length() == 2); |
5180 | 5176 |
5181 maybe_close = factory()->NewBlock(nullptr, 1, true, nopos); | 5177 maybe_close = factory()->NewBlock(nullptr, 1, true, nopos); |
5182 maybe_close->statements()->Add( | 5178 maybe_close->statements()->Add( |
5183 factory()->NewIfStatement(condition, block, | 5179 factory()->NewIfStatement(condition, block, |
5184 factory()->NewEmptyStatement(nopos), nopos), | 5180 factory()->NewEmptyStatement(nopos), nopos), |
5185 zone()); | 5181 zone()); |
5186 } | 5182 } |
5187 | 5183 |
5188 // try { #try_block } | 5184 // try { #try_block } |
5189 // catch(e) { | 5185 // catch(e) { |
5190 // #set_completion_throw; | 5186 // #set_completion_throw; |
5191 // %ReThrow(e); | 5187 // %ReThrow(e); |
5192 // } | 5188 // } |
5193 Statement* try_catch; | 5189 Statement* try_catch; |
5194 { | 5190 { |
5195 Scope* catch_scope = NewScopeWithParent(use_scope, CATCH_SCOPE); | 5191 Scope* catch_scope = NewScopeWithParent(scope(), CATCH_SCOPE); |
5196 Variable* catch_variable = | 5192 Variable* catch_variable = |
5197 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, | 5193 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, |
5198 kCreatedInitialized, NORMAL_VARIABLE); | 5194 kCreatedInitialized, NORMAL_VARIABLE); |
5199 catch_scope->set_is_hidden(); | 5195 catch_scope->set_is_hidden(); |
5200 | 5196 |
5201 Statement* rethrow; | 5197 Statement* rethrow; |
5202 // We use %ReThrow rather than the ordinary throw because we want to | 5198 // We use %ReThrow rather than the ordinary throw because we want to |
5203 // preserve the original exception message. This is also why we create a | 5199 // preserve the original exception message. This is also why we create a |
5204 // TryCatchStatementForReThrow below (which does not clear the pending | 5200 // TryCatchStatementForReThrow below (which does not clear the pending |
5205 // message), rather than a TryCatchStatement. | 5201 // message), rather than a TryCatchStatement. |
(...skipping 19 matching lines...) Expand all Loading... |
5225 try_block->statements()->Add(try_catch, zone()); | 5221 try_block->statements()->Add(try_catch, zone()); |
5226 | 5222 |
5227 try_finally = | 5223 try_finally = |
5228 factory()->NewTryFinallyStatement(try_block, maybe_close, nopos); | 5224 factory()->NewTryFinallyStatement(try_block, maybe_close, nopos); |
5229 } | 5225 } |
5230 | 5226 |
5231 target->statements()->Add(initialize_completion, zone()); | 5227 target->statements()->Add(initialize_completion, zone()); |
5232 target->statements()->Add(try_finally, zone()); | 5228 target->statements()->Add(try_finally, zone()); |
5233 } | 5229 } |
5234 | 5230 |
5235 void Parser::BuildIteratorCloseForCompletion(Scope* scope, | 5231 void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements, |
5236 ZoneList<Statement*>* statements, | |
5237 Variable* iterator, | 5232 Variable* iterator, |
5238 Expression* completion) { | 5233 Expression* completion) { |
5239 // | 5234 // |
5240 // This function adds two statements to [statements], corresponding to the | 5235 // This function adds two statements to [statements], corresponding to the |
5241 // following code: | 5236 // following code: |
5242 // | 5237 // |
5243 // let iteratorReturn = iterator.return; | 5238 // let iteratorReturn = iterator.return; |
5244 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { | 5239 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { |
5245 // if (completion === kThrowCompletion) { | 5240 // if (completion === kThrowCompletion) { |
5246 // if (!IS_CALLABLE(iteratorReturn)) { | 5241 // if (!IS_CALLABLE(iteratorReturn)) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5292 | 5287 |
5293 Expression* call = | 5288 Expression* call = |
5294 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); | 5289 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
5295 | 5290 |
5296 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); | 5291 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); |
5297 try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos), | 5292 try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos), |
5298 zone()); | 5293 zone()); |
5299 | 5294 |
5300 Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos); | 5295 Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos); |
5301 | 5296 |
5302 Scope* catch_scope = NewScopeWithParent(scope, CATCH_SCOPE); | 5297 Scope* catch_scope = NewScope(CATCH_SCOPE); |
5303 Variable* catch_variable = | 5298 Variable* catch_variable = |
5304 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, | 5299 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, |
5305 kCreatedInitialized, NORMAL_VARIABLE); | 5300 kCreatedInitialized, NORMAL_VARIABLE); |
5306 catch_scope->set_is_hidden(); | 5301 catch_scope->set_is_hidden(); |
5307 | 5302 |
5308 try_call_return = factory()->NewTryCatchStatement( | 5303 try_call_return = factory()->NewTryCatchStatement( |
5309 try_block, catch_scope, catch_variable, catch_block, nopos); | 5304 try_block, catch_scope, catch_variable, catch_block, nopos); |
5310 } | 5305 } |
5311 | 5306 |
5312 // let output = %_Call(iteratorReturn, iterator); | 5307 // let output = %_Call(iteratorReturn, iterator); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5429 closing_condition = factory()->NewUnaryOperation( | 5424 closing_condition = factory()->NewUnaryOperation( |
5430 Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos), | 5425 Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos), |
5431 nopos); | 5426 nopos); |
5432 } | 5427 } |
5433 | 5428 |
5434 Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos); | 5429 Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos); |
5435 { | 5430 { |
5436 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); | 5431 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); |
5437 try_block->statements()->Add(loop, zone()); | 5432 try_block->statements()->Add(loop, zone()); |
5438 | 5433 |
5439 // The scope in which the parser creates this loop. | 5434 FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(), |
5440 Scope* loop_scope = scope()->outer_scope(); | 5435 try_block, final_loop); |
5441 DCHECK_EQ(loop_scope->scope_type(), BLOCK_SCOPE); | |
5442 DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE); | |
5443 | |
5444 FinalizeIteratorUse(loop_scope, var_completion, closing_condition, | |
5445 loop->iterator(), try_block, final_loop); | |
5446 } | 5436 } |
5447 | 5437 |
5448 return final_loop; | 5438 return final_loop; |
5449 } | 5439 } |
5450 | 5440 |
5451 #undef CHECK_OK | 5441 #undef CHECK_OK |
5452 #undef CHECK_OK_VOID | 5442 #undef CHECK_OK_VOID |
5453 #undef CHECK_FAILED | 5443 #undef CHECK_FAILED |
5454 | 5444 |
5455 } // namespace internal | 5445 } // namespace internal |
5456 } // namespace v8 | 5446 } // namespace v8 |
OLD | NEW |