pattern-rewriter.cc 23.2 KB
Newer Older
1 2 3 4
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/ast/ast.h"
6
#include "src/messages.h"
7 8
#include "src/parsing/parameter-initializer-rewriter.h"
#include "src/parsing/parser.h"
9 10 11 12 13

namespace v8 {

namespace internal {

14 15 16 17 18
void Parser::PatternRewriter::DeclareAndInitializeVariables(
    Block* block, const DeclarationDescriptor* declaration_descriptor,
    const DeclarationParsingResult::Declaration* declaration,
    ZoneList<const AstRawString*>* names, bool* ok) {
  PatternRewriter rewriter;
19

20 21 22
  rewriter.scope_ = declaration_descriptor->scope;
  rewriter.parser_ = declaration_descriptor->parser;
  rewriter.context_ = BINDING;
23 24 25 26 27 28
  rewriter.pattern_ = declaration->pattern;
  rewriter.initializer_position_ = declaration->initializer_position;
  rewriter.block_ = block;
  rewriter.descriptor_ = declaration_descriptor;
  rewriter.names_ = names;
  rewriter.ok_ = ok;
29
  rewriter.recursion_level_ = 0;
30

31
  rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
32 33 34
}


35
void Parser::PatternRewriter::RewriteDestructuringAssignment(
36
    Parser* parser, RewritableAssignmentExpression* to_rewrite, Scope* scope) {
37 38 39 40
  PatternRewriter rewriter;

  DCHECK(!to_rewrite->is_rewritten());

41
  bool ok = true;
42 43 44 45 46 47 48
  rewriter.scope_ = scope;
  rewriter.parser_ = parser;
  rewriter.context_ = ASSIGNMENT;
  rewriter.pattern_ = to_rewrite;
  rewriter.block_ = nullptr;
  rewriter.descriptor_ = nullptr;
  rewriter.names_ = nullptr;
49
  rewriter.ok_ = &ok;
50
  rewriter.recursion_level_ = 0;
51 52

  rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr);
53 54 55 56 57 58 59 60 61 62 63 64
  DCHECK(ok);
}


Expression* Parser::PatternRewriter::RewriteDestructuringAssignment(
    Parser* parser, Assignment* assignment, Scope* scope) {
  DCHECK_NOT_NULL(assignment);
  DCHECK_EQ(Token::ASSIGN, assignment->op());
  auto to_rewrite =
      parser->factory()->NewRewritableAssignmentExpression(assignment);
  RewriteDestructuringAssignment(parser, to_rewrite, scope);
  return to_rewrite->expression();
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
}


bool Parser::PatternRewriter::IsAssignmentContext(PatternContext c) const {
  return c == ASSIGNMENT || c == ASSIGNMENT_INITIALIZER;
}


bool Parser::PatternRewriter::IsBindingContext(PatternContext c) const {
  return c == BINDING || c == INITIALIZER;
}


Parser::PatternRewriter::PatternContext
Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
  PatternContext old_context = context();
  if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN) {
    set_context(ASSIGNMENT);
  }
  return old_context;
}


Parser::PatternRewriter::PatternContext
Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) {
  // Set appropriate initializer context for BindingElement and
  // AssignmentElement nodes
  PatternContext old_context = context();
  bool is_destructuring_assignment =
      node->IsRewritableAssignmentExpression() &&
      !node->AsRewritableAssignmentExpression()->is_rewritten();
  bool is_assignment =
      node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN;
  if (is_destructuring_assignment || is_assignment) {
    switch (old_context) {
      case BINDING:
        set_context(INITIALIZER);
        break;
      case ASSIGNMENT:
        set_context(ASSIGNMENT_INITIALIZER);
        break;
      default:
        break;
    }
  }
  return old_context;
}


114 115
void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
  Expression* value = current_value_;
116 117 118 119 120 121

  if (IsAssignmentContext()) {
    // In an assignment context, simply perform the assignment
    Assignment* assignment = factory()->NewAssignment(
        Token::ASSIGN, pattern, value, pattern->position());
    block_->statements()->Add(
122
        factory()->NewExpressionStatement(assignment, pattern->position()),
123 124 125 126
        zone());
    return;
  }

127
  descriptor_->scope->RemoveUnresolved(pattern);
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

  // Declare variable.
  // Note that we *always* must treat the initial value via a separate init
  // assignment for variables and constants because the value must be assigned
  // when the variable is encountered in the source. But the variable/constant
  // is declared (and set to 'undefined') upon entering the function within
  // which the variable or constant is declared. Only function variables have
  // an initial value in the declaration (because they are initialized upon
  // entering the function).
  //
  // If we have a legacy const declaration, in an inner scope, the proxy
  // is always bound to the declared variable (independent of possibly
  // surrounding 'with' statements).
  // For let/const declarations in harmony mode, we can also immediately
  // pre-resolve the proxy because it resides in the same scope as the
  // declaration.
  const AstRawString* name = pattern->raw_name();
145
  VariableProxy* proxy = parser_->NewUnresolved(name, descriptor_->mode);
146
  Declaration* declaration = factory()->NewVariableDeclaration(
147 148
      proxy, descriptor_->mode, descriptor_->scope,
      descriptor_->declaration_pos);
149 150 151
  Variable* var =
      parser_->Declare(declaration, descriptor_->declaration_kind,
                       descriptor_->mode != VAR, ok_, descriptor_->hoist_scope);
152 153 154
  if (!*ok_) return;
  DCHECK_NOT_NULL(var);
  DCHECK(!proxy->is_resolved() || proxy->var() == var);
155 156 157 158
  var->set_initializer_position(initializer_position_);

  DCHECK(initializer_position_ != RelocInfo::kNoPosition);

159 160 161 162
  Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode)
                                 ? descriptor_->scope
                                 : descriptor_->scope->DeclarationScope();
  if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
163
    parser_->ReportMessage(MessageTemplate::kTooManyVariables);
164 165 166
    *ok_ = false;
    return;
  }
167 168
  if (names_) {
    names_->Add(name, zone());
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
  }

  // Initialize variables if needed. A
  // declaration of the form:
  //
  //    var v = x;
  //
  // is syntactic sugar for:
  //
  //    var v; v = x;
  //
  // In particular, we need to re-lookup 'v' (in scope_, not
  // declaration_scope) as it may be a different 'v' than the 'v' in the
  // declaration (e.g., if we are inside a 'with' statement or 'catch'
  // block).
  //
  // However, note that const declarations are different! A const
  // declaration of the form:
  //
  //   const c = x;
  //
  // is *not* syntactic sugar for:
  //
  //   const c; c = x;
  //
  // The "variable" c initialized to x is the same as the declared
  // one - there is no re-lookup (see the last parameter of the
  // Declare() call above).
197 198
  Scope* initialization_scope = IsImmutableVariableMode(descriptor_->mode)
                                    ? declaration_scope
199
                                    : descriptor_->scope;
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220


  // Global variable declarations must be compiled in a specific
  // way. When the script containing the global variable declaration
  // is entered, the global variable must be declared, so that if it
  // doesn't exist (on the global object itself, see ES5 errata) it
  // gets created with an initial undefined value. This is handled
  // by the declarations part of the function representing the
  // top-level global code; see Runtime::DeclareGlobalVariable. If
  // it already exists (in the object or in a prototype), it is
  // *not* touched until the variable declaration statement is
  // executed.
  //
  // Executing the variable declaration statement will always
  // guarantee to give the global object an own property.
  // This way, global variable declarations can shadow
  // properties in the prototype chain, but only after the variable
  // declaration statement has been executed. This is important in
  // browsers where the global object (window) has lots of
  // properties defined in prototype objects.
  if (initialization_scope->is_script_scope() &&
221
      !IsLexicalVariableMode(descriptor_->mode)) {
222 223 224 225 226
    // Compute the arguments for the runtime
    // call.test-parsing/InitializedDeclarationsInStrictForOfError
    ZoneList<Expression*>* arguments =
        new (zone()) ZoneList<Expression*>(3, zone());
    // We have at least 1 parameter.
227 228 229
    arguments->Add(
        factory()->NewStringLiteral(name, descriptor_->declaration_pos),
        zone());
230 231
    CallRuntime* initialize;

232
    if (IsImmutableVariableMode(descriptor_->mode)) {
233 234 235 236 237 238 239
      arguments->Add(value, zone());
      value = NULL;  // zap the value to avoid the unnecessary assignment

      // Construct the call to Runtime_InitializeConstGlobal
      // and add it to the initialization statement block.
      // Note that the function does different things depending on
      // the number of arguments (1 or 2).
240 241 242
      initialize =
          factory()->NewCallRuntime(Runtime::kInitializeConstGlobal, arguments,
                                    descriptor_->initialization_pos);
243 244 245 246
    } else {
      // Add language mode.
      // We may want to pass singleton to avoid Literal allocations.
      LanguageMode language_mode = initialization_scope->language_mode();
247 248 249
      arguments->Add(factory()->NewNumberLiteral(language_mode,
                                                 descriptor_->declaration_pos),
                     zone());
250 251 252 253 254

      // Be careful not to assign a value to the global variable if
      // we're in a with. The initialization value should not
      // necessarily be stored in the global object in that case,
      // which is why we need to generate a separate assignment node.
255
      if (value != NULL && !descriptor_->scope->inside_with()) {
256 257 258 259
        arguments->Add(value, zone());
        value = NULL;  // zap the value to avoid the unnecessary assignment
        // Construct the call to Runtime_InitializeVarGlobal
        // and add it to the initialization statement block.
260 261 262
        initialize =
            factory()->NewCallRuntime(Runtime::kInitializeVarGlobal, arguments,
                                      descriptor_->declaration_pos);
263 264 265 266 267 268
      } else {
        initialize = NULL;
      }
    }

    if (initialize != NULL) {
neis's avatar
neis committed
269
      block_->statements()->Add(
270 271 272
          factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
          zone());
    }
273
  } else if (value != nullptr && (descriptor_->mode == CONST_LEGACY ||
274
                                  IsLexicalVariableMode(descriptor_->mode))) {
275 276 277 278 279 280 281 282 283 284
    // Constant initializations always assign to the declared constant which
    // is always at the function scope level. This is only relevant for
    // dynamically looked-up variables and constants (the
    // start context for constant lookups is always the function context,
    // while it is the top context for var declared variables). Sigh...
    // For 'let' and 'const' declared variables in harmony mode the
    // initialization also always assigns to the declared variable.
    DCHECK_NOT_NULL(proxy);
    DCHECK_NOT_NULL(proxy->var());
    DCHECK_NOT_NULL(value);
285 286 287 288
    // Add break location for destructured sub-pattern.
    int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
    Assignment* assignment =
        factory()->NewAssignment(Token::INIT, proxy, value, pos);
neis's avatar
neis committed
289
    block_->statements()->Add(
290
        factory()->NewExpressionStatement(assignment, pos), zone());
291 292 293 294 295 296
    value = NULL;
  }

  // Add an assignment node to the initialization statement block if we still
  // have a pending initialization value.
  if (value != NULL) {
297
    DCHECK(descriptor_->mode == VAR);
298 299 300 301
    // 'var' initializations are simply assignments (with all the consequences
    // if they are inside a 'with' statement - they may change a 'with' object
    // property).
    VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name);
302 303 304 305
    // Add break location for destructured sub-pattern.
    int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
    Assignment* assignment =
        factory()->NewAssignment(Token::INIT, proxy, value, pos);
neis's avatar
neis committed
306
    block_->statements()->Add(
307
        factory()->NewExpressionStatement(assignment, pos), zone());
308 309 310 311
  }
}


312
Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
313
  auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
314 315 316 317
  if (value != nullptr) {
    auto assignment = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(temp), value,
        RelocInfo::kNoPosition);
318

neis's avatar
neis committed
319
    block_->statements()->Add(
320 321 322
        factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
        zone());
  }
323 324 325
  return temp;
}

326

327 328 329 330 331 332 333 334 335
void Parser::PatternRewriter::VisitRewritableAssignmentExpression(
    RewritableAssignmentExpression* node) {
  if (!IsAssignmentContext()) {
    // Mark the assignment as rewritten to prevent redundant rewriting, and
    // perform BindingPattern rewriting
    DCHECK(!node->is_rewritten());
    node->Rewrite(node->expression());
    return node->expression()->Accept(this);
  }
336

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
  if (node->is_rewritten()) return;
  DCHECK(IsAssignmentContext());
  Assignment* assign = node->expression()->AsAssignment();
  DCHECK_NOT_NULL(assign);
  DCHECK_EQ(Token::ASSIGN, assign->op());

  auto initializer = assign->value();
  auto value = initializer;

  if (IsInitializerContext()) {
    // let {<pattern> = <init>} = <value>
    //   becomes
    // temp = <value>;
    // <pattern> = temp === undefined ? <init> : temp;
    auto temp_var = CreateTempVar(current_value_);
    Expression* is_undefined = factory()->NewCompareOperation(
        Token::EQ_STRICT, factory()->NewVariableProxy(temp_var),
        factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
        RelocInfo::kNoPosition);
    value = factory()->NewConditional(is_undefined, initializer,
                                      factory()->NewVariableProxy(temp_var),
                                      RelocInfo::kNoPosition);
  }

  PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
  int pos = assign->position();
  Block* old_block = block_;
  block_ = factory()->NewBlock(nullptr, 8, false, pos);
  Variable* temp = nullptr;
  Expression* pattern = assign->target();
  Expression* old_value = current_value_;
  current_value_ = value;
  if (pattern->IsObjectLiteral()) {
    VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
  } else {
    DCHECK(pattern->IsArrayLiteral());
    VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
  }
  DCHECK_NOT_NULL(temp);
  current_value_ = old_value;
  Expression* expr = factory()->NewDoExpression(block_, temp, pos);
  node->Rewrite(expr);
  block_ = old_block;
  if (block_) {
    block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
                              zone());
  }
  return set_context(old_context);
}


void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
                                                 Variable** temp_var) {
  auto temp = *temp_var = CreateTempVar(current_value_);

  block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
393

394
  for (ObjectLiteralProperty* property : *pattern->properties()) {
395
    PatternContext context = SetInitializerContextIfNeeded(property->value());
396 397 398 399
    RecurseIntoSubpattern(
        property->value(),
        factory()->NewProperty(factory()->NewVariableProxy(temp),
                               property->key(), RelocInfo::kNoPosition));
400
    set_context(context);
401 402 403 404
  }
}


405 406 407 408 409
void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
  Variable* temp_var = nullptr;
  VisitObjectLiteral(node, &temp_var);
}

410

411 412 413
void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
                                                Variable** temp_var) {
  auto temp = *temp_var = CreateTempVar(current_value_);
414

415 416 417
  block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());

  auto iterator = CreateTempVar(parser_->GetIterator(
418
      factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
419 420 421 422
  auto done = CreateTempVar(
      factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
  auto result = CreateTempVar();
  auto v = CreateTempVar();
423 424

  Spread* spread = nullptr;
425
  for (Expression* value : *node->values()) {
426 427 428 429 430
    if (value->IsSpread()) {
      spread = value->AsSpread();
      break;
    }

431
    PatternContext context = SetInitializerContextIfNeeded(value);
432 433 434 435 436 437
    // if (!done) {
    //   result = IteratorNext(iterator);
    //   v = (done = result.done) ? undefined : result.value;
    // }
    auto next_block =
        factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
438 439 440 441 442 443
    next_block->statements()->Add(factory()->NewExpressionStatement(
                                      parser_->BuildIteratorNextResult(
                                          factory()->NewVariableProxy(iterator),
                                          result, RelocInfo::kNoPosition),
                                      RelocInfo::kNoPosition),
                                  zone());
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460

    auto assign_to_done = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(done),
        factory()->NewProperty(
            factory()->NewVariableProxy(result),
            factory()->NewStringLiteral(ast_value_factory()->done_string(),
                                        RelocInfo::kNoPosition),
            RelocInfo::kNoPosition),
        RelocInfo::kNoPosition);
    auto next_value = factory()->NewConditional(
        assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
        factory()->NewProperty(
            factory()->NewVariableProxy(result),
            factory()->NewStringLiteral(ast_value_factory()->value_string(),
                                        RelocInfo::kNoPosition),
            RelocInfo::kNoPosition),
        RelocInfo::kNoPosition);
neis's avatar
neis committed
461
    next_block->statements()->Add(
462 463 464 465 466 467 468 469 470 471 472 473 474
        factory()->NewExpressionStatement(
            factory()->NewAssignment(Token::ASSIGN,
                                     factory()->NewVariableProxy(v), next_value,
                                     RelocInfo::kNoPosition),
            RelocInfo::kNoPosition),
        zone());

    auto if_statement = factory()->NewIfStatement(
        factory()->NewUnaryOperation(Token::NOT,
                                     factory()->NewVariableProxy(done),
                                     RelocInfo::kNoPosition),
        next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
        RelocInfo::kNoPosition);
neis's avatar
neis committed
475
    block_->statements()->Add(if_statement, zone());
476 477 478 479

    if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
      RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
    }
480
    set_context(context);
481
  }
482 483 484

  if (spread != nullptr) {
    // array = [];
485
    // if (!done) %concat_iterable_to_array(array, iterator);
486 487 488 489 490
    auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
    auto array = CreateTempVar(factory()->NewArrayLiteral(
        empty_exprs,
        // Reuse pattern's literal index - it is unused since there is no
        // actual literal allocated.
491
        node->literal_index(), is_strong(scope()->language_mode()),
492 493 494 495 496
        RelocInfo::kNoPosition));

    auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
    arguments->Add(factory()->NewVariableProxy(array), zone());
    arguments->Add(factory()->NewVariableProxy(iterator), zone());
497 498 499
    auto spread_into_array_call =
        factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
                                  arguments, RelocInfo::kNoPosition);
500 501 502 503 504 505 506 507 508

    auto if_statement = factory()->NewIfStatement(
        factory()->NewUnaryOperation(Token::NOT,
                                     factory()->NewVariableProxy(done),
                                     RelocInfo::kNoPosition),
        factory()->NewExpressionStatement(spread_into_array_call,
                                          RelocInfo::kNoPosition),
        factory()->NewEmptyStatement(RelocInfo::kNoPosition),
        RelocInfo::kNoPosition);
neis's avatar
neis committed
509
    block_->statements()->Add(if_statement, zone());
510 511 512 513

    RecurseIntoSubpattern(spread->expression(),
                          factory()->NewVariableProxy(array));
  }
514 515 516
}


517 518 519 520 521 522
void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
  Variable* temp_var = nullptr;
  VisitArrayLiteral(node, &temp_var);
}


523
void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
524 525 526 527
  // let {<pattern> = <init>} = <value>
  //   becomes
  // temp = <value>;
  // <pattern> = temp === undefined ? <init> : temp;
528 529 530 531
  DCHECK_EQ(Token::ASSIGN, node->op());

  auto initializer = node->value();
  auto value = initializer;
532
  auto temp = CreateTempVar(current_value_);
533 534 535 536 537 538 539 540 541

  if (IsInitializerContext()) {
    Expression* is_undefined = factory()->NewCompareOperation(
        Token::EQ_STRICT, factory()->NewVariableProxy(temp),
        factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
        RelocInfo::kNoPosition);
    value = factory()->NewConditional(is_undefined, initializer,
                                      factory()->NewVariableProxy(temp),
                                      RelocInfo::kNoPosition);
542
  }
543 544 545 546 547 548 549 550 551

  if (IsBindingContext() &&
      descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
      scope()->is_arrow_scope()) {
    RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
                                     scope()->outer_scope(), scope());
  }

  PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
552
  RecurseIntoSubpattern(node->target(), value);
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
  set_context(old_context);
}


// =============== AssignmentPattern only ==================

void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
  DCHECK(IsAssignmentContext());
  auto value = current_value_;

  Assignment* assignment =
      factory()->NewAssignment(Token::ASSIGN, node, value, node->position());

  block_->statements()->Add(
      factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
      zone());
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
}


// =============== UNREACHABLE =============================

void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }

#define NOT_A_PATTERN(Node)                                        \
  void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
    UNREACHABLE();                                                 \
  }

NOT_A_PATTERN(BinaryOperation)
NOT_A_PATTERN(Block)
NOT_A_PATTERN(BreakStatement)
NOT_A_PATTERN(Call)
NOT_A_PATTERN(CallNew)
NOT_A_PATTERN(CallRuntime)
NOT_A_PATTERN(CaseClause)
NOT_A_PATTERN(ClassLiteral)
NOT_A_PATTERN(CompareOperation)
NOT_A_PATTERN(Conditional)
NOT_A_PATTERN(ContinueStatement)
NOT_A_PATTERN(CountOperation)
NOT_A_PATTERN(DebuggerStatement)
594
NOT_A_PATTERN(DoExpression)
595 596
NOT_A_PATTERN(DoWhileStatement)
NOT_A_PATTERN(EmptyStatement)
597
NOT_A_PATTERN(EmptyParentheses)
598 599 600 601 602 603 604 605 606 607 608 609 610
NOT_A_PATTERN(ExportDeclaration)
NOT_A_PATTERN(ExpressionStatement)
NOT_A_PATTERN(ForInStatement)
NOT_A_PATTERN(ForOfStatement)
NOT_A_PATTERN(ForStatement)
NOT_A_PATTERN(FunctionDeclaration)
NOT_A_PATTERN(FunctionLiteral)
NOT_A_PATTERN(IfStatement)
NOT_A_PATTERN(ImportDeclaration)
NOT_A_PATTERN(Literal)
NOT_A_PATTERN(NativeFunctionLiteral)
NOT_A_PATTERN(RegExpLiteral)
NOT_A_PATTERN(ReturnStatement)
611 612
NOT_A_PATTERN(SloppyBlockFunctionStatement)
NOT_A_PATTERN(Spread)
613 614
NOT_A_PATTERN(SuperPropertyReference)
NOT_A_PATTERN(SuperCallReference)
615 616 617 618 619 620 621 622 623 624 625 626
NOT_A_PATTERN(SwitchStatement)
NOT_A_PATTERN(ThisFunction)
NOT_A_PATTERN(Throw)
NOT_A_PATTERN(TryCatchStatement)
NOT_A_PATTERN(TryFinallyStatement)
NOT_A_PATTERN(UnaryOperation)
NOT_A_PATTERN(VariableDeclaration)
NOT_A_PATTERN(WhileStatement)
NOT_A_PATTERN(WithStatement)
NOT_A_PATTERN(Yield)

#undef NOT_A_PATTERN
627 628
}  // namespace internal
}  // namespace v8