1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/ast/ast.h" 6 #include "src/messages.h" 7 #include "src/parsing/parameter-initializer-rewriter.h" 8 #include "src/parsing/parser.h" 9 10 namespace v8 { 11 12 namespace internal { 13 14 void Parser::PatternRewriter::DeclareAndInitializeVariables( 15 Parser* parser, Block* block, 16 const DeclarationDescriptor* declaration_descriptor, 17 const DeclarationParsingResult::Declaration* declaration, 18 ZoneList<const AstRawString*>* names, bool* ok) { 19 PatternRewriter rewriter; 20 21 DCHECK(block->ignore_completion_value()); 22 23 rewriter.scope_ = declaration_descriptor->scope; 24 rewriter.parser_ = parser; 25 rewriter.context_ = BINDING; 26 rewriter.pattern_ = declaration->pattern; 27 rewriter.initializer_position_ = declaration->initializer_position; 28 rewriter.block_ = block; 29 rewriter.descriptor_ = declaration_descriptor; 30 rewriter.names_ = names; 31 rewriter.ok_ = ok; 32 rewriter.recursion_level_ = 0; 33 34 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer); 35 } 36 37 38 void Parser::PatternRewriter::RewriteDestructuringAssignment( 39 Parser* parser, RewritableExpression* to_rewrite, Scope* scope) { 40 DCHECK(!scope->HasBeenRemoved()); 41 DCHECK(!to_rewrite->is_rewritten()); 42 43 bool ok = true; 44 45 PatternRewriter rewriter; 46 rewriter.scope_ = scope; 47 rewriter.parser_ = parser; 48 rewriter.context_ = ASSIGNMENT; 49 rewriter.pattern_ = to_rewrite; 50 rewriter.block_ = nullptr; 51 rewriter.descriptor_ = nullptr; 52 rewriter.names_ = nullptr; 53 rewriter.ok_ = &ok; 54 rewriter.recursion_level_ = 0; 55 56 rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr); 57 DCHECK(ok); 58 } 59 60 61 Expression* Parser::PatternRewriter::RewriteDestructuringAssignment( 62 Parser* parser, Assignment* assignment, Scope* scope) { 63 DCHECK_NOT_NULL(assignment); 64 DCHECK_EQ(Token::ASSIGN, assignment->op()); 65 auto to_rewrite = parser->factory()->NewRewritableExpression(assignment); 66 RewriteDestructuringAssignment(parser, to_rewrite, scope); 67 return to_rewrite->expression(); 68 } 69 70 71 Parser::PatternRewriter::PatternContext 72 Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) { 73 PatternContext old_context = context(); 74 // AssignmentExpressions may occur in the Initializer position of a 75 // SingleNameBinding. Such expressions should not prompt a change in the 76 // pattern's context. 77 if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN && 78 !IsInitializerContext()) { 79 set_context(ASSIGNMENT); 80 } 81 return old_context; 82 } 83 84 85 Parser::PatternRewriter::PatternContext 86 Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) { 87 // Set appropriate initializer context for BindingElement and 88 // AssignmentElement nodes 89 PatternContext old_context = context(); 90 bool is_destructuring_assignment = 91 node->IsRewritableExpression() && 92 !node->AsRewritableExpression()->is_rewritten(); 93 bool is_assignment = 94 node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN; 95 if (is_destructuring_assignment || is_assignment) { 96 switch (old_context) { 97 case BINDING: 98 set_context(INITIALIZER); 99 break; 100 case ASSIGNMENT: 101 set_context(ASSIGNMENT_INITIALIZER); 102 break; 103 default: 104 break; 105 } 106 } 107 return old_context; 108 } 109 110 111 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { 112 Expression* value = current_value_; 113 114 if (IsAssignmentContext()) { 115 // In an assignment context, simply perform the assignment 116 Assignment* assignment = factory()->NewAssignment( 117 Token::ASSIGN, pattern, value, pattern->position()); 118 block_->statements()->Add( 119 factory()->NewExpressionStatement(assignment, pattern->position()), 120 zone()); 121 return; 122 } 123 124 descriptor_->scope->RemoveUnresolved(pattern); 125 126 // Declare variable. 127 // Note that we *always* must treat the initial value via a separate init 128 // assignment for variables and constants because the value must be assigned 129 // when the variable is encountered in the source. But the variable/constant 130 // is declared (and set to 'undefined') upon entering the function within 131 // which the variable or constant is declared. Only function variables have 132 // an initial value in the declaration (because they are initialized upon 133 // entering the function). 134 const AstRawString* name = pattern->raw_name(); 135 VariableProxy* proxy = 136 factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position()); 137 Declaration* declaration = factory()->NewVariableDeclaration( 138 proxy, descriptor_->scope, descriptor_->declaration_pos); 139 Variable* var = parser_->Declare( 140 declaration, descriptor_->declaration_kind, descriptor_->mode, 141 Variable::DefaultInitializationFlag(descriptor_->mode), ok_, 142 descriptor_->hoist_scope); 143 if (!*ok_) return; 144 DCHECK_NOT_NULL(var); 145 DCHECK(proxy->is_resolved()); 146 DCHECK(initializer_position_ != kNoSourcePosition); 147 var->set_initializer_position(initializer_position_); 148 149 // TODO(adamk): This should probably be checking hoist_scope. 150 // Move it to Parser::Declare() to make it easier to test 151 // the right scope. 152 Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode) 153 ? descriptor_->scope 154 : descriptor_->scope->GetDeclarationScope(); 155 if (declaration_scope->num_var() > kMaxNumFunctionLocals) { 156 parser_->ReportMessage(MessageTemplate::kTooManyVariables); 157 *ok_ = false; 158 return; 159 } 160 if (names_) { 161 names_->Add(name, zone()); 162 } 163 164 // If there's no initializer, we're done. 165 if (value == nullptr) return; 166 167 // A declaration of the form: 168 // 169 // var v = x; 170 // 171 // is syntactic sugar for: 172 // 173 // var v; v = x; 174 // 175 // In particular, we need to re-lookup 'v' as it may be a different 176 // 'v' than the 'v' in the declaration (e.g., if we are inside a 177 // 'with' statement or 'catch' block). Global var declarations 178 // also need special treatment. 179 Scope* var_init_scope = descriptor_->scope; 180 181 if (descriptor_->mode == VAR && var_init_scope->is_script_scope()) { 182 // Global variable declarations must be compiled in a specific 183 // way. When the script containing the global variable declaration 184 // is entered, the global variable must be declared, so that if it 185 // doesn't exist (on the global object itself, see ES5 errata) it 186 // gets created with an initial undefined value. This is handled 187 // by the declarations part of the function representing the 188 // top-level global code; see Runtime::DeclareGlobalVariable. If 189 // it already exists (in the object or in a prototype), it is 190 // *not* touched until the variable declaration statement is 191 // executed. 192 // 193 // Executing the variable declaration statement will always 194 // guarantee to give the global object an own property. 195 // This way, global variable declarations can shadow 196 // properties in the prototype chain, but only after the variable 197 // declaration statement has been executed. This is important in 198 // browsers where the global object (window) has lots of 199 // properties defined in prototype objects. 200 201 ZoneList<Expression*>* arguments = 202 new (zone()) ZoneList<Expression*>(3, zone()); 203 arguments->Add( 204 factory()->NewStringLiteral(name, descriptor_->declaration_pos), 205 zone()); 206 arguments->Add(factory()->NewNumberLiteral(var_init_scope->language_mode(), 207 kNoSourcePosition), 208 zone()); 209 arguments->Add(value, zone()); 210 211 CallRuntime* initialize = factory()->NewCallRuntime( 212 Runtime::kInitializeVarGlobal, arguments, value->position()); 213 block_->statements()->Add( 214 factory()->NewExpressionStatement(initialize, initialize->position()), 215 zone()); 216 } else { 217 // For 'let' and 'const' declared variables the initialization always 218 // assigns to the declared variable. 219 // But for var declarations we need to do a new lookup. 220 if (descriptor_->mode == VAR) { 221 proxy = var_init_scope->NewUnresolved(factory(), name); 222 } else { 223 DCHECK_NOT_NULL(proxy); 224 DCHECK_NOT_NULL(proxy->var()); 225 } 226 // Add break location for destructured sub-pattern. 227 int pos = IsSubPattern() ? pattern->position() : value->position(); 228 Assignment* assignment = 229 factory()->NewAssignment(Token::INIT, proxy, value, pos); 230 block_->statements()->Add( 231 factory()->NewExpressionStatement(assignment, pos), zone()); 232 } 233 } 234 235 236 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { 237 auto temp = scope()->NewTemporary(ast_value_factory()->empty_string()); 238 if (value != nullptr) { 239 auto assignment = factory()->NewAssignment( 240 Token::ASSIGN, factory()->NewVariableProxy(temp), value, 241 kNoSourcePosition); 242 243 block_->statements()->Add( 244 factory()->NewExpressionStatement(assignment, kNoSourcePosition), 245 zone()); 246 } 247 return temp; 248 } 249 250 251 void Parser::PatternRewriter::VisitRewritableExpression( 252 RewritableExpression* node) { 253 // If this is not a destructuring assignment... 254 if (!IsAssignmentContext()) { 255 // Mark the node as rewritten to prevent redundant rewriting, and 256 // perform BindingPattern rewriting 257 DCHECK(!node->is_rewritten()); 258 node->Rewrite(node->expression()); 259 return Visit(node->expression()); 260 } else if (!node->expression()->IsAssignment()) { 261 return Visit(node->expression()); 262 } 263 264 if (node->is_rewritten()) return; 265 DCHECK(IsAssignmentContext()); 266 Assignment* assign = node->expression()->AsAssignment(); 267 DCHECK_NOT_NULL(assign); 268 DCHECK_EQ(Token::ASSIGN, assign->op()); 269 270 auto initializer = assign->value(); 271 auto value = initializer; 272 273 if (IsInitializerContext()) { 274 // let {<pattern> = <init>} = <value> 275 // becomes 276 // temp = <value>; 277 // <pattern> = temp === undefined ? <init> : temp; 278 auto temp_var = CreateTempVar(current_value_); 279 Expression* is_undefined = factory()->NewCompareOperation( 280 Token::EQ_STRICT, factory()->NewVariableProxy(temp_var), 281 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition); 282 value = factory()->NewConditional(is_undefined, initializer, 283 factory()->NewVariableProxy(temp_var), 284 kNoSourcePosition); 285 } 286 287 PatternContext old_context = SetAssignmentContextIfNeeded(initializer); 288 int pos = assign->position(); 289 Block* old_block = block_; 290 block_ = factory()->NewBlock(nullptr, 8, true, pos); 291 Variable* temp = nullptr; 292 Expression* pattern = assign->target(); 293 Expression* old_value = current_value_; 294 current_value_ = value; 295 if (pattern->IsObjectLiteral()) { 296 VisitObjectLiteral(pattern->AsObjectLiteral(), &temp); 297 } else { 298 DCHECK(pattern->IsArrayLiteral()); 299 VisitArrayLiteral(pattern->AsArrayLiteral(), &temp); 300 } 301 DCHECK_NOT_NULL(temp); 302 current_value_ = old_value; 303 Expression* expr = factory()->NewDoExpression(block_, temp, pos); 304 node->Rewrite(expr); 305 block_ = old_block; 306 if (block_) { 307 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos), 308 zone()); 309 } 310 return set_context(old_context); 311 } 312 313 // When an extra declaration scope needs to be inserted to account for 314 // a sloppy eval in a default parameter or function body, the expressions 315 // needs to be in that new inner scope which was added after initial 316 // parsing. 317 void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) { 318 if (!IsBindingContext()) return; 319 if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return; 320 if (!scope()->is_block_scope()) return; 321 322 DCHECK(scope()->is_declaration_scope()); 323 DCHECK(scope()->outer_scope()->is_function_scope()); 324 DCHECK(scope()->calls_sloppy_eval()); 325 326 ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope()); 327 } 328 329 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern, 330 Variable** temp_var) { 331 auto temp = *temp_var = CreateTempVar(current_value_); 332 333 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone()); 334 335 for (ObjectLiteralProperty* property : *pattern->properties()) { 336 PatternContext context = SetInitializerContextIfNeeded(property->value()); 337 338 // Computed property names contain expressions which might require 339 // scope rewriting. 340 if (!property->key()->IsLiteral()) RewriteParameterScopes(property->key()); 341 342 RecurseIntoSubpattern( 343 property->value(), 344 factory()->NewProperty(factory()->NewVariableProxy(temp), 345 property->key(), kNoSourcePosition)); 346 set_context(context); 347 } 348 } 349 350 351 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) { 352 Variable* temp_var = nullptr; 353 VisitObjectLiteral(node, &temp_var); 354 } 355 356 357 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node, 358 Variable** temp_var) { 359 DCHECK(block_->ignore_completion_value()); 360 361 auto temp = *temp_var = CreateTempVar(current_value_); 362 auto iterator = CreateTempVar(parser_->GetIterator( 363 factory()->NewVariableProxy(temp), kNoSourcePosition)); 364 auto done = 365 CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition)); 366 auto result = CreateTempVar(); 367 auto v = CreateTempVar(); 368 auto completion = CreateTempVar(); 369 auto nopos = kNoSourcePosition; 370 371 // For the purpose of iterator finalization, we temporarily set block_ to a 372 // new block. In the main body of this function, we write to block_ (both 373 // explicitly and implicitly via recursion). At the end of the function, we 374 // wrap this new block in a try-finally statement, restore block_ to its 375 // original value, and add the try-finally statement to block_. 376 auto target = block_; 377 block_ = factory()->NewBlock(nullptr, 8, true, nopos); 378 379 Spread* spread = nullptr; 380 for (Expression* value : *node->values()) { 381 if (value->IsSpread()) { 382 spread = value->AsSpread(); 383 break; 384 } 385 386 PatternContext context = SetInitializerContextIfNeeded(value); 387 388 // if (!done) { 389 // done = true; // If .next, .done or .value throws, don't close. 390 // result = IteratorNext(iterator); 391 // if (result.done) { 392 // v = undefined; 393 // } else { 394 // v = result.value; 395 // done = false; 396 // } 397 // } 398 Statement* if_not_done; 399 { 400 auto result_done = factory()->NewProperty( 401 factory()->NewVariableProxy(result), 402 factory()->NewStringLiteral(ast_value_factory()->done_string(), 403 kNoSourcePosition), 404 kNoSourcePosition); 405 406 auto assign_undefined = factory()->NewAssignment( 407 Token::ASSIGN, factory()->NewVariableProxy(v), 408 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition); 409 410 auto assign_value = factory()->NewAssignment( 411 Token::ASSIGN, factory()->NewVariableProxy(v), 412 factory()->NewProperty( 413 factory()->NewVariableProxy(result), 414 factory()->NewStringLiteral(ast_value_factory()->value_string(), 415 kNoSourcePosition), 416 kNoSourcePosition), 417 kNoSourcePosition); 418 419 auto unset_done = factory()->NewAssignment( 420 Token::ASSIGN, factory()->NewVariableProxy(done), 421 factory()->NewBooleanLiteral(false, kNoSourcePosition), 422 kNoSourcePosition); 423 424 auto inner_else = 425 factory()->NewBlock(nullptr, 2, true, kNoSourcePosition); 426 inner_else->statements()->Add( 427 factory()->NewExpressionStatement(assign_value, nopos), zone()); 428 inner_else->statements()->Add( 429 factory()->NewExpressionStatement(unset_done, nopos), zone()); 430 431 auto inner_if = factory()->NewIfStatement( 432 result_done, 433 factory()->NewExpressionStatement(assign_undefined, nopos), 434 inner_else, nopos); 435 436 auto next_block = 437 factory()->NewBlock(nullptr, 3, true, kNoSourcePosition); 438 next_block->statements()->Add( 439 factory()->NewExpressionStatement( 440 factory()->NewAssignment( 441 Token::ASSIGN, factory()->NewVariableProxy(done), 442 factory()->NewBooleanLiteral(true, nopos), nopos), 443 nopos), 444 zone()); 445 next_block->statements()->Add( 446 factory()->NewExpressionStatement( 447 parser_->BuildIteratorNextResult( 448 factory()->NewVariableProxy(iterator), result, 449 kNoSourcePosition), 450 kNoSourcePosition), 451 zone()); 452 next_block->statements()->Add(inner_if, zone()); 453 454 if_not_done = factory()->NewIfStatement( 455 factory()->NewUnaryOperation( 456 Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition), 457 next_block, factory()->NewEmptyStatement(kNoSourcePosition), 458 kNoSourcePosition); 459 } 460 block_->statements()->Add(if_not_done, zone()); 461 462 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) { 463 { 464 // completion = kAbruptCompletion; 465 Expression* proxy = factory()->NewVariableProxy(completion); 466 Expression* assignment = factory()->NewAssignment( 467 Token::ASSIGN, proxy, 468 factory()->NewSmiLiteral(kAbruptCompletion, nopos), nopos); 469 block_->statements()->Add( 470 factory()->NewExpressionStatement(assignment, nopos), zone()); 471 } 472 473 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v)); 474 475 { 476 // completion = kNormalCompletion; 477 Expression* proxy = factory()->NewVariableProxy(completion); 478 Expression* assignment = factory()->NewAssignment( 479 Token::ASSIGN, proxy, 480 factory()->NewSmiLiteral(kNormalCompletion, nopos), nopos); 481 block_->statements()->Add( 482 factory()->NewExpressionStatement(assignment, nopos), zone()); 483 } 484 } 485 set_context(context); 486 } 487 488 if (spread != nullptr) { 489 // A spread can only occur as the last component. It is not handled by 490 // RecurseIntoSubpattern above. 491 492 // let array = []; 493 // while (!done) { 494 // done = true; // If .next, .done or .value throws, don't close. 495 // result = IteratorNext(iterator); 496 // if (!result.done) { 497 // %AppendElement(array, result.value); 498 // done = false; 499 // } 500 // } 501 502 // let array = []; 503 Variable* array; 504 { 505 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); 506 array = CreateTempVar(factory()->NewArrayLiteral( 507 empty_exprs, 508 // Reuse pattern's literal index - it is unused since there is no 509 // actual literal allocated. 510 node->literal_index(), kNoSourcePosition)); 511 } 512 513 // done = true; 514 Statement* set_done = factory()->NewExpressionStatement( 515 factory()->NewAssignment( 516 Token::ASSIGN, factory()->NewVariableProxy(done), 517 factory()->NewBooleanLiteral(true, nopos), nopos), 518 nopos); 519 520 // result = IteratorNext(iterator); 521 Statement* get_next = factory()->NewExpressionStatement( 522 parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator), 523 result, nopos), 524 nopos); 525 526 // %AppendElement(array, result.value); 527 Statement* append_element; 528 { 529 auto args = new (zone()) ZoneList<Expression*>(2, zone()); 530 args->Add(factory()->NewVariableProxy(array), zone()); 531 args->Add(factory()->NewProperty( 532 factory()->NewVariableProxy(result), 533 factory()->NewStringLiteral( 534 ast_value_factory()->value_string(), nopos), 535 nopos), 536 zone()); 537 append_element = factory()->NewExpressionStatement( 538 factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos), 539 nopos); 540 } 541 542 // done = false; 543 Statement* unset_done = factory()->NewExpressionStatement( 544 factory()->NewAssignment( 545 Token::ASSIGN, factory()->NewVariableProxy(done), 546 factory()->NewBooleanLiteral(false, nopos), nopos), 547 nopos); 548 549 // if (!result.done) { #append_element; #unset_done } 550 Statement* maybe_append_and_unset_done; 551 { 552 Expression* result_done = 553 factory()->NewProperty(factory()->NewVariableProxy(result), 554 factory()->NewStringLiteral( 555 ast_value_factory()->done_string(), nopos), 556 nopos); 557 558 Block* then = factory()->NewBlock(nullptr, 2, true, nopos); 559 then->statements()->Add(append_element, zone()); 560 then->statements()->Add(unset_done, zone()); 561 562 maybe_append_and_unset_done = factory()->NewIfStatement( 563 factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then, 564 factory()->NewEmptyStatement(nopos), nopos); 565 } 566 567 // while (!done) { 568 // #set_done; 569 // #get_next; 570 // #maybe_append_and_unset_done; 571 // } 572 WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos); 573 { 574 Expression* condition = factory()->NewUnaryOperation( 575 Token::NOT, factory()->NewVariableProxy(done), nopos); 576 Block* body = factory()->NewBlock(nullptr, 3, true, nopos); 577 body->statements()->Add(set_done, zone()); 578 body->statements()->Add(get_next, zone()); 579 body->statements()->Add(maybe_append_and_unset_done, zone()); 580 loop->Initialize(condition, body); 581 } 582 583 block_->statements()->Add(loop, zone()); 584 RecurseIntoSubpattern(spread->expression(), 585 factory()->NewVariableProxy(array)); 586 } 587 588 Expression* closing_condition = factory()->NewUnaryOperation( 589 Token::NOT, factory()->NewVariableProxy(done), nopos); 590 591 parser_->FinalizeIteratorUse(scope(), completion, closing_condition, iterator, 592 block_, target); 593 block_ = target; 594 } 595 596 597 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { 598 Variable* temp_var = nullptr; 599 VisitArrayLiteral(node, &temp_var); 600 } 601 602 603 void Parser::PatternRewriter::VisitAssignment(Assignment* node) { 604 // let {<pattern> = <init>} = <value> 605 // becomes 606 // temp = <value>; 607 // <pattern> = temp === undefined ? <init> : temp; 608 DCHECK_EQ(Token::ASSIGN, node->op()); 609 610 auto initializer = node->value(); 611 auto value = initializer; 612 auto temp = CreateTempVar(current_value_); 613 614 if (IsInitializerContext()) { 615 Expression* is_undefined = factory()->NewCompareOperation( 616 Token::EQ_STRICT, factory()->NewVariableProxy(temp), 617 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition); 618 value = factory()->NewConditional(is_undefined, initializer, 619 factory()->NewVariableProxy(temp), 620 kNoSourcePosition); 621 } 622 623 // Initializer may have been parsed in the wrong scope. 624 RewriteParameterScopes(initializer); 625 626 PatternContext old_context = SetAssignmentContextIfNeeded(initializer); 627 RecurseIntoSubpattern(node->target(), value); 628 set_context(old_context); 629 } 630 631 632 // =============== AssignmentPattern only ================== 633 634 void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) { 635 DCHECK(IsAssignmentContext()); 636 auto value = current_value_; 637 638 Assignment* assignment = 639 factory()->NewAssignment(Token::ASSIGN, node, value, node->position()); 640 641 block_->statements()->Add( 642 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone()); 643 } 644 645 646 // =============== UNREACHABLE ============================= 647 648 #define NOT_A_PATTERN(Node) \ 649 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \ 650 UNREACHABLE(); \ 651 } 652 653 NOT_A_PATTERN(BinaryOperation) 654 NOT_A_PATTERN(Block) 655 NOT_A_PATTERN(BreakStatement) 656 NOT_A_PATTERN(Call) 657 NOT_A_PATTERN(CallNew) 658 NOT_A_PATTERN(CallRuntime) 659 NOT_A_PATTERN(CaseClause) 660 NOT_A_PATTERN(ClassLiteral) 661 NOT_A_PATTERN(CompareOperation) 662 NOT_A_PATTERN(Conditional) 663 NOT_A_PATTERN(ContinueStatement) 664 NOT_A_PATTERN(CountOperation) 665 NOT_A_PATTERN(DebuggerStatement) 666 NOT_A_PATTERN(DoExpression) 667 NOT_A_PATTERN(DoWhileStatement) 668 NOT_A_PATTERN(EmptyStatement) 669 NOT_A_PATTERN(EmptyParentheses) 670 NOT_A_PATTERN(ExpressionStatement) 671 NOT_A_PATTERN(ForInStatement) 672 NOT_A_PATTERN(ForOfStatement) 673 NOT_A_PATTERN(ForStatement) 674 NOT_A_PATTERN(FunctionDeclaration) 675 NOT_A_PATTERN(FunctionLiteral) 676 NOT_A_PATTERN(IfStatement) 677 NOT_A_PATTERN(Literal) 678 NOT_A_PATTERN(NativeFunctionLiteral) 679 NOT_A_PATTERN(RegExpLiteral) 680 NOT_A_PATTERN(ReturnStatement) 681 NOT_A_PATTERN(SloppyBlockFunctionStatement) 682 NOT_A_PATTERN(Spread) 683 NOT_A_PATTERN(SuperPropertyReference) 684 NOT_A_PATTERN(SuperCallReference) 685 NOT_A_PATTERN(SwitchStatement) 686 NOT_A_PATTERN(ThisFunction) 687 NOT_A_PATTERN(Throw) 688 NOT_A_PATTERN(TryCatchStatement) 689 NOT_A_PATTERN(TryFinallyStatement) 690 NOT_A_PATTERN(UnaryOperation) 691 NOT_A_PATTERN(VariableDeclaration) 692 NOT_A_PATTERN(WhileStatement) 693 NOT_A_PATTERN(WithStatement) 694 NOT_A_PATTERN(Yield) 695 696 #undef NOT_A_PATTERN 697 } // namespace internal 698 } // namespace v8 699