Chromium Code Reviews| 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-visitor.h" | 10 #include "src/ast/ast-expression-visitor.h" |
| 10 #include "src/ast/ast-literal-reindexer.h" | 11 #include "src/ast/ast-literal-reindexer.h" |
| 11 #include "src/ast/scopeinfo.h" | 12 #include "src/ast/scopeinfo.h" |
| 12 #include "src/bailout-reason.h" | 13 #include "src/bailout-reason.h" |
| 13 #include "src/base/platform/platform.h" | 14 #include "src/base/platform/platform.h" |
| 14 #include "src/bootstrapper.h" | 15 #include "src/bootstrapper.h" |
| 15 #include "src/char-predicates-inl.h" | 16 #include "src/char-predicates-inl.h" |
| 16 #include "src/codegen.h" | 17 #include "src/codegen.h" |
| 17 #include "src/compiler.h" | 18 #include "src/compiler.h" |
| 18 #include "src/messages.h" | 19 #include "src/messages.h" |
| (...skipping 5378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5397 return parser_->RewriteExpression(expr); | 5398 return parser_->RewriteExpression(expr); |
| 5398 } | 5399 } |
| 5399 | 5400 |
| 5400 | 5401 |
| 5401 ObjectLiteralProperty* ParserTraits::RewriteObjectLiteralProperty( | 5402 ObjectLiteralProperty* ParserTraits::RewriteObjectLiteralProperty( |
| 5402 ObjectLiteralProperty* property) { | 5403 ObjectLiteralProperty* property) { |
| 5403 return parser_->RewriteObjectLiteralProperty(property); | 5404 return parser_->RewriteObjectLiteralProperty(property); |
| 5404 } | 5405 } |
| 5405 | 5406 |
| 5406 | 5407 |
| 5408 class SpreadRewriter : public AstExpressionRewriter { | |
| 5409 public: | |
| 5410 SpreadRewriter(uintptr_t stack_limit, Parser* parser) | |
| 5411 : AstExpressionRewriter(stack_limit), parser_(parser) {} | |
| 5412 ~SpreadRewriter() override {} | |
| 5413 | |
| 5414 private: | |
| 5415 bool RewriteExpression(Expression* expr) override { | |
| 5416 // Rewrite only what could have been a pattern. | |
| 5417 // The actual work is in array literals. | |
| 5418 if (expr->IsArrayLiteral()) { | |
| 5419 ArrayLiteral* lit = expr->AsArrayLiteral(); | |
| 5420 VisitExpressions(lit->values()); | |
| 5421 replacement_ = parser_->RewriteSpreads(lit); | |
| 5422 return false; | |
| 5423 } | |
| 5424 if (expr->IsObjectLiteral()) { | |
| 5425 return true; | |
| 5426 } | |
| 5427 if (expr->IsBinaryOperation() && | |
| 5428 expr->AsBinaryOperation()->op() == Token::COMMA) { | |
| 5429 return true; | |
| 5430 } | |
| 5431 // Everything else does not need rewriting. | |
| 5432 return false; | |
| 5433 } | |
| 5434 | |
| 5435 Parser* parser_; | |
| 5436 }; | |
| 5437 | |
| 5438 | |
| 5407 Expression* Parser::RewriteExpression(Expression* expr) { | 5439 Expression* Parser::RewriteExpression(Expression* expr) { |
| 5408 // TODO(nikolaos): For the time being, this does no rewriting at all. | 5440 SpreadRewriter rewriter(stack_limit_, this); |
| 5409 return expr; | 5441 AstNode* node = rewriter.Rewrite(expr); |
| 5442 DCHECK_NOT_NULL(node); | |
|
rossberg
2016/01/11 12:50:14
Nit: having 2 null checks here may be a bit over-d
nickie
2016/01/13 10:15:21
Acknowledged. I will remove the first. It was pr
| |
| 5443 Expression* result = reinterpret_cast<Expression*>(node); | |
| 5444 DCHECK_NOT_NULL(result); | |
| 5445 return result; | |
| 5410 } | 5446 } |
| 5411 | 5447 |
| 5412 | 5448 |
| 5413 ObjectLiteralProperty* Parser::RewriteObjectLiteralProperty( | 5449 ObjectLiteralProperty* Parser::RewriteObjectLiteralProperty( |
| 5414 ObjectLiteralProperty* property) { | 5450 ObjectLiteralProperty* property) { |
| 5415 if (property != nullptr) { | 5451 if (property != nullptr) { |
| 5416 Expression* key = RewriteExpression(property->key()); | 5452 Expression* key = RewriteExpression(property->key()); |
| 5417 property->set_key(key); | 5453 property->set_key(key); |
| 5418 Expression* value = RewriteExpression(property->value()); | 5454 Expression* value = RewriteExpression(property->value()); |
| 5419 property->set_value(value); | 5455 property->set_value(value); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 5435 pair.assignment->AsRewritableAssignmentExpression(); | 5471 pair.assignment->AsRewritableAssignmentExpression(); |
| 5436 Scope* scope = pair.scope; | 5472 Scope* scope = pair.scope; |
| 5437 DCHECK_NOT_NULL(to_rewrite); | 5473 DCHECK_NOT_NULL(to_rewrite); |
| 5438 if (!to_rewrite->is_rewritten()) { | 5474 if (!to_rewrite->is_rewritten()) { |
| 5439 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); | 5475 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); |
| 5440 } | 5476 } |
| 5441 } | 5477 } |
| 5442 } | 5478 } |
| 5443 | 5479 |
| 5444 | 5480 |
| 5481 Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { | |
| 5482 ZoneList<Expression*>::iterator s = lit->FirstSpread(); | |
| 5483 if (s == lit->EndValue()) return nullptr; | |
| 5484 // TODO(nikolaos): Check and fix the positions for the generated AST. | |
| 5485 Variable* result = | |
| 5486 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
| 5487 Expression* init_result = | |
| 5488 factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result), | |
| 5489 lit, RelocInfo::kNoPosition); | |
| 5490 Block* do_block = | |
| 5491 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); | |
| 5492 do_block->statements()->Add( | |
| 5493 factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition), | |
| 5494 zone()); | |
| 5495 while (s != lit->EndValue()) { | |
| 5496 Expression* value = *s++; | |
| 5497 Spread* spread = value->AsSpread(); | |
| 5498 if (spread == nullptr) { | |
|
rossberg
2016/01/11 12:50:14
Nit: add comments to both branches of this conditi
nickie
2016/01/13 10:15:21
Acknowledged.
| |
| 5499 ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone()); | |
| 5500 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | |
| 5501 append_element_args->Add(value, zone()); | |
| 5502 do_block->statements()->Add( | |
| 5503 factory()->NewExpressionStatement( | |
| 5504 factory()->NewCallRuntime(Runtime::kAppendElement, | |
| 5505 append_element_args, | |
| 5506 RelocInfo::kNoPosition), | |
| 5507 RelocInfo::kNoPosition), | |
| 5508 zone()); | |
| 5509 } else { | |
| 5510 Variable* each = | |
| 5511 scope_->NewTemporary(ast_value_factory()->dot_for_string()); | |
| 5512 Expression* subject = spread->expression(); | |
| 5513 Variable* iterator = | |
| 5514 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); | |
| 5515 Variable* element = | |
| 5516 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
| 5517 // iterator = subject[Symbol.iterator]() | |
| 5518 Expression* assign_iterator = factory()->NewAssignment( | |
| 5519 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
| 5520 GetIterator(subject, factory(), spread->position()), | |
| 5521 spread->position()); | |
| 5522 // !%_IsJSReceiver(element = iterator.next()) && | |
| 5523 // %ThrowIteratorResultNotAnObject(element) | |
| 5524 Expression* next_element; | |
| 5525 { | |
| 5526 // element = iterator.next() | |
| 5527 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
| 5528 next_element = BuildIteratorNextResult(iterator_proxy, element, | |
| 5529 spread->position()); | |
| 5530 } | |
| 5531 // element.done | |
| 5532 Expression* element_done; | |
| 5533 { | |
| 5534 Expression* done_literal = factory()->NewStringLiteral( | |
| 5535 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
| 5536 Expression* element_proxy = factory()->NewVariableProxy(element); | |
| 5537 element_done = factory()->NewProperty(element_proxy, done_literal, | |
| 5538 RelocInfo::kNoPosition); | |
| 5539 } | |
| 5540 // each = element.value | |
| 5541 Expression* assign_each; | |
| 5542 { | |
| 5543 Expression* value_literal = factory()->NewStringLiteral( | |
| 5544 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
| 5545 Expression* element_proxy = factory()->NewVariableProxy(element); | |
| 5546 Expression* element_value = factory()->NewProperty( | |
| 5547 element_proxy, value_literal, RelocInfo::kNoPosition); | |
| 5548 assign_each = factory()->NewAssignment( | |
| 5549 Token::ASSIGN, factory()->NewVariableProxy(each), element_value, | |
| 5550 RelocInfo::kNoPosition); | |
| 5551 } | |
| 5552 // append each to the result | |
| 5553 Statement* append_body; | |
| 5554 { | |
| 5555 ZoneList<Expression*>* append_element_args = | |
| 5556 NewExpressionList(2, zone()); | |
| 5557 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | |
| 5558 append_element_args->Add(factory()->NewVariableProxy(each), zone()); | |
| 5559 append_body = factory()->NewExpressionStatement( | |
| 5560 factory()->NewCallRuntime(Runtime::kAppendElement, | |
| 5561 append_element_args, | |
| 5562 RelocInfo::kNoPosition), | |
| 5563 RelocInfo::kNoPosition); | |
| 5564 } | |
| 5565 ForEachStatement* loop = factory()->NewForEachStatement( | |
| 5566 ForEachStatement::ITERATE, nullptr, spread->position()); | |
| 5567 ForOfStatement* for_of = loop->AsForOfStatement(); | |
| 5568 for_of->Initialize(factory()->NewVariableProxy(each), subject, | |
| 5569 append_body, assign_iterator, next_element, | |
| 5570 element_done, assign_each); | |
| 5571 do_block->statements()->Add(for_of, zone()); | |
| 5572 } | |
| 5573 } | |
| 5574 lit->RewindSpreads(); | |
|
rossberg
2016/01/11 12:50:14
Why is this needed?
nickie
2016/01/13 10:15:21
This is very important. Line 5487 initializes the
| |
| 5575 return factory()->NewDoExpression(do_block, result, lit->position()); | |
| 5576 } | |
| 5577 | |
| 5578 | |
| 5445 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 5579 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
| 5446 DCHECK(expr->IsRewritableAssignmentExpression()); | 5580 DCHECK(expr->IsRewritableAssignmentExpression()); |
| 5447 parser_->function_state_->AddDestructuringAssignment( | 5581 parser_->function_state_->AddDestructuringAssignment( |
| 5448 Parser::DestructuringAssignment(expr, parser_->scope_)); | 5582 Parser::DestructuringAssignment(expr, parser_->scope_)); |
| 5449 } | 5583 } |
| 5450 | 5584 |
| 5451 | 5585 |
| 5452 void ParserTraits::SetFunctionNameFromPropertyName( | 5586 void ParserTraits::SetFunctionNameFromPropertyName( |
| 5453 ObjectLiteralProperty* property, const AstRawString* name) { | 5587 ObjectLiteralProperty* property, const AstRawString* name) { |
| 5454 Expression* value = property->value(); | 5588 Expression* value = property->value(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 5482 auto class_literal = value->AsClassLiteral(); | 5616 auto class_literal = value->AsClassLiteral(); |
| 5483 if (class_literal->raw_name() == nullptr) { | 5617 if (class_literal->raw_name() == nullptr) { |
| 5484 class_literal->set_raw_name(name); | 5618 class_literal->set_raw_name(name); |
| 5485 } | 5619 } |
| 5486 } | 5620 } |
| 5487 } | 5621 } |
| 5488 | 5622 |
| 5489 | 5623 |
| 5490 } // namespace internal | 5624 } // namespace internal |
| 5491 } // namespace v8 | 5625 } // namespace v8 |
| OLD | NEW |