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 5385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5404 | 5405 |
5405 | 5406 |
5406 ObjectLiteralProperty* ParserTraits::RewriteNonPatternObjectLiteralProperty( | 5407 ObjectLiteralProperty* ParserTraits::RewriteNonPatternObjectLiteralProperty( |
5407 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, | 5408 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, |
5408 bool* ok) { | 5409 bool* ok) { |
5409 return parser_->RewriteNonPatternObjectLiteralProperty(property, classifier, | 5410 return parser_->RewriteNonPatternObjectLiteralProperty(property, classifier, |
5410 ok); | 5411 ok); |
5411 } | 5412 } |
5412 | 5413 |
5413 | 5414 |
5415 class NonPatternRewriter : public AstExpressionRewriter { | |
5416 public: | |
5417 NonPatternRewriter(uintptr_t stack_limit, Parser* parser) | |
5418 : AstExpressionRewriter(stack_limit), parser_(parser) {} | |
5419 ~NonPatternRewriter() override {} | |
5420 | |
5421 private: | |
5422 bool RewriteExpression(Expression* expr) override { | |
5423 // Rewrite only what could have been a pattern but is not. | |
5424 if (expr->IsArrayLiteral()) { | |
5425 // Spread rewriting in array literals. | |
5426 ArrayLiteral* lit = expr->AsArrayLiteral(); | |
5427 VisitExpressions(lit->values()); | |
5428 replacement_ = parser_->RewriteSpreads(lit); | |
5429 return false; | |
5430 } | |
5431 if (expr->IsObjectLiteral()) { | |
5432 return true; | |
5433 } | |
5434 if (expr->IsBinaryOperation() && | |
5435 expr->AsBinaryOperation()->op() == Token::COMMA) { | |
5436 return true; | |
5437 } | |
5438 // Everything else does not need rewriting. | |
5439 return false; | |
5440 } | |
5441 | |
5442 Parser* parser_; | |
5443 }; | |
5444 | |
5445 | |
5414 Expression* Parser::RewriteNonPattern(Expression* expr, | 5446 Expression* Parser::RewriteNonPattern(Expression* expr, |
5415 const ExpressionClassifier* classifier, | 5447 const ExpressionClassifier* classifier, |
5416 bool* ok) { | 5448 bool* ok) { |
5417 // For the time being, this does no rewriting at all. | |
5418 ValidateExpression(classifier, ok); | 5449 ValidateExpression(classifier, ok); |
5419 return expr; | 5450 if (!*ok) return expr; |
5451 NonPatternRewriter rewriter(stack_limit_, this); | |
5452 Expression* result = reinterpret_cast<Expression*>(rewriter.Rewrite(expr)); | |
5453 DCHECK_NOT_NULL(result); | |
5454 return result; | |
nickie
2016/01/14 16:35:02
This is almost trivial; rewriting happens after va
| |
5420 } | 5455 } |
5421 | 5456 |
5422 | 5457 |
5423 ZoneList<Expression*>* Parser::RewriteNonPatternArguments( | 5458 ZoneList<Expression*>* Parser::RewriteNonPatternArguments( |
5424 ZoneList<Expression*>* args, const ExpressionClassifier* classifier, | 5459 ZoneList<Expression*>* args, const ExpressionClassifier* classifier, |
5425 bool* ok) { | 5460 bool* ok) { |
5426 // For the time being, this does no rewriting at all. | |
5427 ValidateExpression(classifier, ok); | 5461 ValidateExpression(classifier, ok); |
5462 if (!*ok) return args; | |
5463 for (int i = 0; i < args->length(); i++) { | |
5464 NonPatternRewriter rewriter(stack_limit_, this); | |
5465 Expression* result = | |
5466 reinterpret_cast<Expression*>(rewriter.Rewrite(args->at(i))); | |
5467 DCHECK_NOT_NULL(result); | |
5468 args->Set(i, result); | |
5469 } | |
nickie
2016/01/14 16:35:02
This is the only non-trivial addition to this reba
| |
5428 return args; | 5470 return args; |
5429 } | 5471 } |
5430 | 5472 |
5431 | 5473 |
5432 ObjectLiteralProperty* Parser::RewriteNonPatternObjectLiteralProperty( | 5474 ObjectLiteralProperty* Parser::RewriteNonPatternObjectLiteralProperty( |
5433 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, | 5475 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, |
5434 bool* ok) { | 5476 bool* ok) { |
5435 if (property != nullptr) { | 5477 if (property != nullptr) { |
5436 Expression* key = RewriteNonPattern(property->key(), classifier, ok); | 5478 Expression* key = RewriteNonPattern(property->key(), classifier, ok); |
5437 property->set_key(key); | 5479 property->set_key(key); |
(...skipping 17 matching lines...) Expand all Loading... | |
5455 pair.assignment->AsRewritableAssignmentExpression(); | 5497 pair.assignment->AsRewritableAssignmentExpression(); |
5456 Scope* scope = pair.scope; | 5498 Scope* scope = pair.scope; |
5457 DCHECK_NOT_NULL(to_rewrite); | 5499 DCHECK_NOT_NULL(to_rewrite); |
5458 if (!to_rewrite->is_rewritten()) { | 5500 if (!to_rewrite->is_rewritten()) { |
5459 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); | 5501 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); |
5460 } | 5502 } |
5461 } | 5503 } |
5462 } | 5504 } |
5463 | 5505 |
5464 | 5506 |
5507 Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { | |
5508 // Array literals containing spreads are rewritten using do expressions, e.g. | |
5509 // [1, 2, 3, ...x, 4, ...y, 5] | |
5510 // is roughly rewritten as: | |
5511 // do { | |
5512 // $R = [1, 2, 3]; | |
5513 // for ($i of x) %AppendElement($R, $i); | |
5514 // %AppendElement($R, 4); | |
5515 // for ($j of y) %AppendElement($R, $j); | |
5516 // %AppendElement($R, 5); | |
5517 // $R | |
5518 // } | |
5519 // where $R, $i and $j are fresh temporary variables. | |
5520 ZoneList<Expression*>::iterator s = lit->FirstSpread(); | |
5521 if (s == lit->EndValue()) return nullptr; // no spread, no rewriting... | |
5522 Variable* result = | |
5523 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
5524 // NOTE: The value assigned to R is the whole original array literal, | |
5525 // spreads included. This will be fixed before the rewritten AST is returned. | |
5526 // $R = lit | |
5527 Expression* init_result = | |
5528 factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result), | |
5529 lit, RelocInfo::kNoPosition); | |
5530 Block* do_block = | |
5531 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); | |
5532 do_block->statements()->Add( | |
5533 factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition), | |
5534 zone()); | |
5535 // Traverse the array literal starting from the first spread. | |
5536 while (s != lit->EndValue()) { | |
5537 Expression* value = *s++; | |
5538 Spread* spread = value->AsSpread(); | |
5539 if (spread == nullptr) { | |
5540 // If the element is not a spread, we're adding a single: | |
5541 // %AppendElement($R, value) | |
5542 ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone()); | |
5543 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | |
5544 append_element_args->Add(value, zone()); | |
5545 do_block->statements()->Add( | |
5546 factory()->NewExpressionStatement( | |
5547 factory()->NewCallRuntime(Runtime::kAppendElement, | |
5548 append_element_args, | |
5549 RelocInfo::kNoPosition), | |
5550 RelocInfo::kNoPosition), | |
5551 zone()); | |
5552 } else { | |
5553 // If it's a spread, we're adding a for/of loop iterating through it. | |
5554 Variable* each = | |
5555 scope_->NewTemporary(ast_value_factory()->dot_for_string()); | |
5556 Expression* subject = spread->expression(); | |
5557 Variable* iterator = | |
5558 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); | |
5559 Variable* element = | |
5560 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
5561 // iterator = subject[Symbol.iterator]() | |
5562 Expression* assign_iterator = factory()->NewAssignment( | |
5563 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
5564 GetIterator(subject, factory(), spread->expression_position()), | |
5565 subject->position()); | |
5566 // !%_IsJSReceiver(element = iterator.next()) && | |
5567 // %ThrowIteratorResultNotAnObject(element) | |
5568 Expression* next_element; | |
5569 { | |
5570 // element = iterator.next() | |
5571 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
5572 next_element = BuildIteratorNextResult(iterator_proxy, element, | |
5573 spread->expression_position()); | |
5574 } | |
5575 // element.done | |
5576 Expression* element_done; | |
5577 { | |
5578 Expression* done_literal = factory()->NewStringLiteral( | |
5579 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
5580 Expression* element_proxy = factory()->NewVariableProxy(element); | |
5581 element_done = factory()->NewProperty(element_proxy, done_literal, | |
5582 RelocInfo::kNoPosition); | |
5583 } | |
5584 // each = element.value | |
5585 Expression* assign_each; | |
5586 { | |
5587 Expression* value_literal = factory()->NewStringLiteral( | |
5588 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
5589 Expression* element_proxy = factory()->NewVariableProxy(element); | |
5590 Expression* element_value = factory()->NewProperty( | |
5591 element_proxy, value_literal, RelocInfo::kNoPosition); | |
5592 assign_each = factory()->NewAssignment( | |
5593 Token::ASSIGN, factory()->NewVariableProxy(each), element_value, | |
5594 RelocInfo::kNoPosition); | |
5595 } | |
5596 // %AppendElement($R, each) | |
5597 Statement* append_body; | |
5598 { | |
5599 ZoneList<Expression*>* append_element_args = | |
5600 NewExpressionList(2, zone()); | |
5601 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | |
5602 append_element_args->Add(factory()->NewVariableProxy(each), zone()); | |
5603 append_body = factory()->NewExpressionStatement( | |
5604 factory()->NewCallRuntime(Runtime::kAppendElement, | |
5605 append_element_args, | |
5606 RelocInfo::kNoPosition), | |
5607 RelocInfo::kNoPosition); | |
5608 } | |
5609 // for (each of spread) %AppendElement($R, each) | |
5610 ForEachStatement* loop = factory()->NewForEachStatement( | |
5611 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); | |
5612 ForOfStatement* for_of = loop->AsForOfStatement(); | |
5613 for_of->Initialize(factory()->NewVariableProxy(each), subject, | |
5614 append_body, assign_iterator, next_element, | |
5615 element_done, assign_each); | |
5616 do_block->statements()->Add(for_of, zone()); | |
5617 } | |
5618 } | |
5619 // Now, rewind the original array literal to truncate everything from the | |
5620 // first spread (included) until the end. This fixes $R's initialization. | |
5621 lit->RewindSpreads(); | |
5622 return factory()->NewDoExpression(do_block, result, lit->position()); | |
5623 } | |
5624 | |
5625 | |
5465 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 5626 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
5466 DCHECK(expr->IsRewritableAssignmentExpression()); | 5627 DCHECK(expr->IsRewritableAssignmentExpression()); |
5467 parser_->function_state_->AddDestructuringAssignment( | 5628 parser_->function_state_->AddDestructuringAssignment( |
5468 Parser::DestructuringAssignment(expr, parser_->scope_)); | 5629 Parser::DestructuringAssignment(expr, parser_->scope_)); |
5469 } | 5630 } |
5470 | 5631 |
5471 | 5632 |
5472 void ParserTraits::SetFunctionNameFromPropertyName( | 5633 void ParserTraits::SetFunctionNameFromPropertyName( |
5473 ObjectLiteralProperty* property, const AstRawString* name) { | 5634 ObjectLiteralProperty* property, const AstRawString* name) { |
5474 Expression* value = property->value(); | 5635 Expression* value = property->value(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5525 auto class_literal = value->AsClassLiteral(); | 5686 auto class_literal = value->AsClassLiteral(); |
5526 if (class_literal->raw_name() == nullptr) { | 5687 if (class_literal->raw_name() == nullptr) { |
5527 class_literal->set_raw_name(name); | 5688 class_literal->set_raw_name(name); |
5528 } | 5689 } |
5529 } | 5690 } |
5530 } | 5691 } |
5531 | 5692 |
5532 | 5693 |
5533 } // namespace internal | 5694 } // namespace internal |
5534 } // namespace v8 | 5695 } // namespace v8 |
OLD | NEW |