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 
DeclareAndInitializeVariables(Block * block,const DeclarationDescriptor * declaration_descriptor,const DeclarationParsingResult::Declaration * declaration,ZoneList<const AstRawString * > * names,bool * ok)14 void Parser::PatternRewriter::DeclareAndInitializeVariables(
15     Block* block, const DeclarationDescriptor* declaration_descriptor,
16     const DeclarationParsingResult::Declaration* declaration,
17     ZoneList<const AstRawString*>* names, bool* ok) {
18   PatternRewriter rewriter;
19 
20   rewriter.scope_ = declaration_descriptor->scope;
21   rewriter.parser_ = declaration_descriptor->parser;
22   rewriter.context_ = BINDING;
23   rewriter.pattern_ = declaration->pattern;
24   rewriter.initializer_position_ = declaration->initializer_position;
25   rewriter.block_ = block;
26   rewriter.descriptor_ = declaration_descriptor;
27   rewriter.names_ = names;
28   rewriter.ok_ = ok;
29   rewriter.recursion_level_ = 0;
30 
31   rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
32 }
33 
34 
RewriteDestructuringAssignment(Parser * parser,RewritableAssignmentExpression * to_rewrite,Scope * scope)35 void Parser::PatternRewriter::RewriteDestructuringAssignment(
36     Parser* parser, RewritableAssignmentExpression* to_rewrite, Scope* scope) {
37   PatternRewriter rewriter;
38 
39   DCHECK(!to_rewrite->is_rewritten());
40 
41   bool ok = true;
42   rewriter.scope_ = scope;
43   rewriter.parser_ = parser;
44   rewriter.context_ = ASSIGNMENT;
45   rewriter.pattern_ = to_rewrite;
46   rewriter.block_ = nullptr;
47   rewriter.descriptor_ = nullptr;
48   rewriter.names_ = nullptr;
49   rewriter.ok_ = &ok;
50   rewriter.recursion_level_ = 0;
51 
52   rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr);
53   DCHECK(ok);
54 }
55 
56 
RewriteDestructuringAssignment(Parser * parser,Assignment * assignment,Scope * scope)57 Expression* Parser::PatternRewriter::RewriteDestructuringAssignment(
58     Parser* parser, Assignment* assignment, Scope* scope) {
59   DCHECK_NOT_NULL(assignment);
60   DCHECK_EQ(Token::ASSIGN, assignment->op());
61   auto to_rewrite =
62       parser->factory()->NewRewritableAssignmentExpression(assignment);
63   RewriteDestructuringAssignment(parser, to_rewrite, scope);
64   return to_rewrite->expression();
65 }
66 
67 
IsAssignmentContext(PatternContext c) const68 bool Parser::PatternRewriter::IsAssignmentContext(PatternContext c) const {
69   return c == ASSIGNMENT || c == ASSIGNMENT_INITIALIZER;
70 }
71 
72 
IsBindingContext(PatternContext c) const73 bool Parser::PatternRewriter::IsBindingContext(PatternContext c) const {
74   return c == BINDING || c == INITIALIZER;
75 }
76 
77 
78 Parser::PatternRewriter::PatternContext
SetAssignmentContextIfNeeded(Expression * node)79 Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
80   PatternContext old_context = context();
81   if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN) {
82     set_context(ASSIGNMENT);
83   }
84   return old_context;
85 }
86 
87 
88 Parser::PatternRewriter::PatternContext
SetInitializerContextIfNeeded(Expression * node)89 Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) {
90   // Set appropriate initializer context for BindingElement and
91   // AssignmentElement nodes
92   PatternContext old_context = context();
93   bool is_destructuring_assignment =
94       node->IsRewritableAssignmentExpression() &&
95       !node->AsRewritableAssignmentExpression()->is_rewritten();
96   bool is_assignment =
97       node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN;
98   if (is_destructuring_assignment || is_assignment) {
99     switch (old_context) {
100       case BINDING:
101         set_context(INITIALIZER);
102         break;
103       case ASSIGNMENT:
104         set_context(ASSIGNMENT_INITIALIZER);
105         break;
106       default:
107         break;
108     }
109   }
110   return old_context;
111 }
112 
113 
VisitVariableProxy(VariableProxy * pattern)114 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
115   Expression* value = current_value_;
116 
117   if (IsAssignmentContext()) {
118     // In an assignment context, simply perform the assignment
119     Assignment* assignment = factory()->NewAssignment(
120         Token::ASSIGN, pattern, value, pattern->position());
121     block_->statements()->Add(
122         factory()->NewExpressionStatement(assignment, pattern->position()),
123         zone());
124     return;
125   }
126 
127   descriptor_->scope->RemoveUnresolved(pattern);
128 
129   // Declare variable.
130   // Note that we *always* must treat the initial value via a separate init
131   // assignment for variables and constants because the value must be assigned
132   // when the variable is encountered in the source. But the variable/constant
133   // is declared (and set to 'undefined') upon entering the function within
134   // which the variable or constant is declared. Only function variables have
135   // an initial value in the declaration (because they are initialized upon
136   // entering the function).
137   //
138   // If we have a legacy const declaration, in an inner scope, the proxy
139   // is always bound to the declared variable (independent of possibly
140   // surrounding 'with' statements).
141   // For let/const declarations in harmony mode, we can also immediately
142   // pre-resolve the proxy because it resides in the same scope as the
143   // declaration.
144   const AstRawString* name = pattern->raw_name();
145   VariableProxy* proxy = parser_->NewUnresolved(name, descriptor_->mode);
146   Declaration* declaration = factory()->NewVariableDeclaration(
147       proxy, descriptor_->mode, descriptor_->scope,
148       descriptor_->declaration_pos);
149   Variable* var =
150       parser_->Declare(declaration, descriptor_->declaration_kind,
151                        descriptor_->mode != VAR, ok_, descriptor_->hoist_scope);
152   if (!*ok_) return;
153   DCHECK_NOT_NULL(var);
154   DCHECK(!proxy->is_resolved() || proxy->var() == var);
155   var->set_initializer_position(initializer_position_);
156 
157   DCHECK(initializer_position_ != RelocInfo::kNoPosition);
158 
159   Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode)
160                                  ? descriptor_->scope
161                                  : descriptor_->scope->DeclarationScope();
162   if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
163     parser_->ReportMessage(MessageTemplate::kTooManyVariables);
164     *ok_ = false;
165     return;
166   }
167   if (names_) {
168     names_->Add(name, zone());
169   }
170 
171   // Initialize variables if needed. A
172   // declaration of the form:
173   //
174   //    var v = x;
175   //
176   // is syntactic sugar for:
177   //
178   //    var v; v = x;
179   //
180   // In particular, we need to re-lookup 'v' (in scope_, not
181   // declaration_scope) as it may be a different 'v' than the 'v' in the
182   // declaration (e.g., if we are inside a 'with' statement or 'catch'
183   // block).
184   //
185   // However, note that const declarations are different! A const
186   // declaration of the form:
187   //
188   //   const c = x;
189   //
190   // is *not* syntactic sugar for:
191   //
192   //   const c; c = x;
193   //
194   // The "variable" c initialized to x is the same as the declared
195   // one - there is no re-lookup (see the last parameter of the
196   // Declare() call above).
197   Scope* initialization_scope = IsImmutableVariableMode(descriptor_->mode)
198                                     ? declaration_scope
199                                     : descriptor_->scope;
200 
201 
202   // Global variable declarations must be compiled in a specific
203   // way. When the script containing the global variable declaration
204   // is entered, the global variable must be declared, so that if it
205   // doesn't exist (on the global object itself, see ES5 errata) it
206   // gets created with an initial undefined value. This is handled
207   // by the declarations part of the function representing the
208   // top-level global code; see Runtime::DeclareGlobalVariable. If
209   // it already exists (in the object or in a prototype), it is
210   // *not* touched until the variable declaration statement is
211   // executed.
212   //
213   // Executing the variable declaration statement will always
214   // guarantee to give the global object an own property.
215   // This way, global variable declarations can shadow
216   // properties in the prototype chain, but only after the variable
217   // declaration statement has been executed. This is important in
218   // browsers where the global object (window) has lots of
219   // properties defined in prototype objects.
220   if (initialization_scope->is_script_scope() &&
221       !IsLexicalVariableMode(descriptor_->mode)) {
222     // Compute the arguments for the runtime
223     // call.test-parsing/InitializedDeclarationsInStrictForOfError
224     ZoneList<Expression*>* arguments =
225         new (zone()) ZoneList<Expression*>(3, zone());
226     // We have at least 1 parameter.
227     arguments->Add(
228         factory()->NewStringLiteral(name, descriptor_->declaration_pos),
229         zone());
230     CallRuntime* initialize;
231 
232     if (IsImmutableVariableMode(descriptor_->mode)) {
233       arguments->Add(value, zone());
234       value = NULL;  // zap the value to avoid the unnecessary assignment
235 
236       // Construct the call to Runtime_InitializeConstGlobal
237       // and add it to the initialization statement block.
238       // Note that the function does different things depending on
239       // the number of arguments (1 or 2).
240       initialize =
241           factory()->NewCallRuntime(Runtime::kInitializeConstGlobal, arguments,
242                                     descriptor_->initialization_pos);
243     } else {
244       // Add language mode.
245       // We may want to pass singleton to avoid Literal allocations.
246       LanguageMode language_mode = initialization_scope->language_mode();
247       arguments->Add(factory()->NewNumberLiteral(language_mode,
248                                                  descriptor_->declaration_pos),
249                      zone());
250 
251       // Be careful not to assign a value to the global variable if
252       // we're in a with. The initialization value should not
253       // necessarily be stored in the global object in that case,
254       // which is why we need to generate a separate assignment node.
255       if (value != NULL && !descriptor_->scope->inside_with()) {
256         arguments->Add(value, zone());
257         value = NULL;  // zap the value to avoid the unnecessary assignment
258         // Construct the call to Runtime_InitializeVarGlobal
259         // and add it to the initialization statement block.
260         initialize =
261             factory()->NewCallRuntime(Runtime::kInitializeVarGlobal, arguments,
262                                       descriptor_->declaration_pos);
263       } else {
264         initialize = NULL;
265       }
266     }
267 
268     if (initialize != NULL) {
269       block_->statements()->Add(
270           factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
271           zone());
272     }
273   } else if (value != nullptr && (descriptor_->mode == CONST_LEGACY ||
274                                   IsLexicalVariableMode(descriptor_->mode))) {
275     // Constant initializations always assign to the declared constant which
276     // is always at the function scope level. This is only relevant for
277     // dynamically looked-up variables and constants (the
278     // start context for constant lookups is always the function context,
279     // while it is the top context for var declared variables). Sigh...
280     // For 'let' and 'const' declared variables in harmony mode the
281     // initialization also always assigns to the declared variable.
282     DCHECK_NOT_NULL(proxy);
283     DCHECK_NOT_NULL(proxy->var());
284     DCHECK_NOT_NULL(value);
285     // Add break location for destructured sub-pattern.
286     int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
287     Assignment* assignment =
288         factory()->NewAssignment(Token::INIT, proxy, value, pos);
289     block_->statements()->Add(
290         factory()->NewExpressionStatement(assignment, pos), zone());
291     value = NULL;
292   }
293 
294   // Add an assignment node to the initialization statement block if we still
295   // have a pending initialization value.
296   if (value != NULL) {
297     DCHECK(descriptor_->mode == VAR);
298     // 'var' initializations are simply assignments (with all the consequences
299     // if they are inside a 'with' statement - they may change a 'with' object
300     // property).
301     VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name);
302     // Add break location for destructured sub-pattern.
303     int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
304     Assignment* assignment =
305         factory()->NewAssignment(Token::INIT, proxy, value, pos);
306     block_->statements()->Add(
307         factory()->NewExpressionStatement(assignment, pos), zone());
308   }
309 }
310 
311 
CreateTempVar(Expression * value)312 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
313   auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
314   if (value != nullptr) {
315     auto assignment = factory()->NewAssignment(
316         Token::ASSIGN, factory()->NewVariableProxy(temp), value,
317         RelocInfo::kNoPosition);
318 
319     block_->statements()->Add(
320         factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
321         zone());
322   }
323   return temp;
324 }
325 
326 
VisitRewritableAssignmentExpression(RewritableAssignmentExpression * node)327 void Parser::PatternRewriter::VisitRewritableAssignmentExpression(
328     RewritableAssignmentExpression* node) {
329   if (!IsAssignmentContext()) {
330     // Mark the assignment as rewritten to prevent redundant rewriting, and
331     // perform BindingPattern rewriting
332     DCHECK(!node->is_rewritten());
333     node->Rewrite(node->expression());
334     return node->expression()->Accept(this);
335   }
336 
337   if (node->is_rewritten()) return;
338   DCHECK(IsAssignmentContext());
339   Assignment* assign = node->expression()->AsAssignment();
340   DCHECK_NOT_NULL(assign);
341   DCHECK_EQ(Token::ASSIGN, assign->op());
342 
343   auto initializer = assign->value();
344   auto value = initializer;
345 
346   if (IsInitializerContext()) {
347     // let {<pattern> = <init>} = <value>
348     //   becomes
349     // temp = <value>;
350     // <pattern> = temp === undefined ? <init> : temp;
351     auto temp_var = CreateTempVar(current_value_);
352     Expression* is_undefined = factory()->NewCompareOperation(
353         Token::EQ_STRICT, factory()->NewVariableProxy(temp_var),
354         factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
355         RelocInfo::kNoPosition);
356     value = factory()->NewConditional(is_undefined, initializer,
357                                       factory()->NewVariableProxy(temp_var),
358                                       RelocInfo::kNoPosition);
359   }
360 
361   PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
362   int pos = assign->position();
363   Block* old_block = block_;
364   block_ = factory()->NewBlock(nullptr, 8, false, pos);
365   Variable* temp = nullptr;
366   Expression* pattern = assign->target();
367   Expression* old_value = current_value_;
368   current_value_ = value;
369   if (pattern->IsObjectLiteral()) {
370     VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
371   } else {
372     DCHECK(pattern->IsArrayLiteral());
373     VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
374   }
375   DCHECK_NOT_NULL(temp);
376   current_value_ = old_value;
377   Expression* expr = factory()->NewDoExpression(block_, temp, pos);
378   node->Rewrite(expr);
379   block_ = old_block;
380   if (block_) {
381     block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
382                               zone());
383   }
384   return set_context(old_context);
385 }
386 
387 
VisitObjectLiteral(ObjectLiteral * pattern,Variable ** temp_var)388 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
389                                                  Variable** temp_var) {
390   auto temp = *temp_var = CreateTempVar(current_value_);
391 
392   block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
393 
394   for (ObjectLiteralProperty* property : *pattern->properties()) {
395     PatternContext context = SetInitializerContextIfNeeded(property->value());
396     RecurseIntoSubpattern(
397         property->value(),
398         factory()->NewProperty(factory()->NewVariableProxy(temp),
399                                property->key(), RelocInfo::kNoPosition));
400     set_context(context);
401   }
402 }
403 
404 
VisitObjectLiteral(ObjectLiteral * node)405 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
406   Variable* temp_var = nullptr;
407   VisitObjectLiteral(node, &temp_var);
408 }
409 
410 
VisitArrayLiteral(ArrayLiteral * node,Variable ** temp_var)411 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
412                                                 Variable** temp_var) {
413   auto temp = *temp_var = CreateTempVar(current_value_);
414 
415   block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
416 
417   auto iterator = CreateTempVar(parser_->GetIterator(
418       factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
419   auto done = CreateTempVar(
420       factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
421   auto result = CreateTempVar();
422   auto v = CreateTempVar();
423 
424   Spread* spread = nullptr;
425   for (Expression* value : *node->values()) {
426     if (value->IsSpread()) {
427       spread = value->AsSpread();
428       break;
429     }
430 
431     PatternContext context = SetInitializerContextIfNeeded(value);
432     // if (!done) {
433     //   result = IteratorNext(iterator);
434     //   v = (done = result.done) ? undefined : result.value;
435     // }
436     auto next_block =
437         factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
438     next_block->statements()->Add(factory()->NewExpressionStatement(
439                                       parser_->BuildIteratorNextResult(
440                                           factory()->NewVariableProxy(iterator),
441                                           result, RelocInfo::kNoPosition),
442                                       RelocInfo::kNoPosition),
443                                   zone());
444 
445     auto assign_to_done = factory()->NewAssignment(
446         Token::ASSIGN, factory()->NewVariableProxy(done),
447         factory()->NewProperty(
448             factory()->NewVariableProxy(result),
449             factory()->NewStringLiteral(ast_value_factory()->done_string(),
450                                         RelocInfo::kNoPosition),
451             RelocInfo::kNoPosition),
452         RelocInfo::kNoPosition);
453     auto next_value = factory()->NewConditional(
454         assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
455         factory()->NewProperty(
456             factory()->NewVariableProxy(result),
457             factory()->NewStringLiteral(ast_value_factory()->value_string(),
458                                         RelocInfo::kNoPosition),
459             RelocInfo::kNoPosition),
460         RelocInfo::kNoPosition);
461     next_block->statements()->Add(
462         factory()->NewExpressionStatement(
463             factory()->NewAssignment(Token::ASSIGN,
464                                      factory()->NewVariableProxy(v), next_value,
465                                      RelocInfo::kNoPosition),
466             RelocInfo::kNoPosition),
467         zone());
468 
469     auto if_statement = factory()->NewIfStatement(
470         factory()->NewUnaryOperation(Token::NOT,
471                                      factory()->NewVariableProxy(done),
472                                      RelocInfo::kNoPosition),
473         next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
474         RelocInfo::kNoPosition);
475     block_->statements()->Add(if_statement, zone());
476 
477     if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
478       RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
479     }
480     set_context(context);
481   }
482 
483   if (spread != nullptr) {
484     // array = [];
485     // if (!done) %concat_iterable_to_array(array, iterator);
486     auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
487     auto array = CreateTempVar(factory()->NewArrayLiteral(
488         empty_exprs,
489         // Reuse pattern's literal index - it is unused since there is no
490         // actual literal allocated.
491         node->literal_index(), is_strong(scope()->language_mode()),
492         RelocInfo::kNoPosition));
493 
494     auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
495     arguments->Add(factory()->NewVariableProxy(array), zone());
496     arguments->Add(factory()->NewVariableProxy(iterator), zone());
497     auto spread_into_array_call =
498         factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
499                                   arguments, RelocInfo::kNoPosition);
500 
501     auto if_statement = factory()->NewIfStatement(
502         factory()->NewUnaryOperation(Token::NOT,
503                                      factory()->NewVariableProxy(done),
504                                      RelocInfo::kNoPosition),
505         factory()->NewExpressionStatement(spread_into_array_call,
506                                           RelocInfo::kNoPosition),
507         factory()->NewEmptyStatement(RelocInfo::kNoPosition),
508         RelocInfo::kNoPosition);
509     block_->statements()->Add(if_statement, zone());
510 
511     RecurseIntoSubpattern(spread->expression(),
512                           factory()->NewVariableProxy(array));
513   }
514 }
515 
516 
VisitArrayLiteral(ArrayLiteral * node)517 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
518   Variable* temp_var = nullptr;
519   VisitArrayLiteral(node, &temp_var);
520 }
521 
522 
VisitAssignment(Assignment * node)523 void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
524   // let {<pattern> = <init>} = <value>
525   //   becomes
526   // temp = <value>;
527   // <pattern> = temp === undefined ? <init> : temp;
528   DCHECK_EQ(Token::ASSIGN, node->op());
529 
530   auto initializer = node->value();
531   auto value = initializer;
532   auto temp = CreateTempVar(current_value_);
533 
534   if (IsInitializerContext()) {
535     Expression* is_undefined = factory()->NewCompareOperation(
536         Token::EQ_STRICT, factory()->NewVariableProxy(temp),
537         factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
538         RelocInfo::kNoPosition);
539     value = factory()->NewConditional(is_undefined, initializer,
540                                       factory()->NewVariableProxy(temp),
541                                       RelocInfo::kNoPosition);
542   }
543 
544   if (IsBindingContext() &&
545       descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
546       scope()->is_arrow_scope()) {
547     RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
548                                      scope()->outer_scope(), scope());
549   }
550 
551   PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
552   RecurseIntoSubpattern(node->target(), value);
553   set_context(old_context);
554 }
555 
556 
557 // =============== AssignmentPattern only ==================
558 
VisitProperty(v8::internal::Property * node)559 void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
560   DCHECK(IsAssignmentContext());
561   auto value = current_value_;
562 
563   Assignment* assignment =
564       factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
565 
566   block_->statements()->Add(
567       factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
568       zone());
569 }
570 
571 
572 // =============== UNREACHABLE =============================
573 
Visit(AstNode * node)574 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }
575 
576 #define NOT_A_PATTERN(Node)                                        \
577   void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
578     UNREACHABLE();                                                 \
579   }
580 
581 NOT_A_PATTERN(BinaryOperation)
582 NOT_A_PATTERN(Block)
583 NOT_A_PATTERN(BreakStatement)
584 NOT_A_PATTERN(Call)
585 NOT_A_PATTERN(CallNew)
586 NOT_A_PATTERN(CallRuntime)
587 NOT_A_PATTERN(CaseClause)
588 NOT_A_PATTERN(ClassLiteral)
589 NOT_A_PATTERN(CompareOperation)
590 NOT_A_PATTERN(Conditional)
591 NOT_A_PATTERN(ContinueStatement)
592 NOT_A_PATTERN(CountOperation)
593 NOT_A_PATTERN(DebuggerStatement)
594 NOT_A_PATTERN(DoExpression)
595 NOT_A_PATTERN(DoWhileStatement)
596 NOT_A_PATTERN(EmptyStatement)
597 NOT_A_PATTERN(EmptyParentheses)
598 NOT_A_PATTERN(ExportDeclaration)
599 NOT_A_PATTERN(ExpressionStatement)
600 NOT_A_PATTERN(ForInStatement)
601 NOT_A_PATTERN(ForOfStatement)
602 NOT_A_PATTERN(ForStatement)
603 NOT_A_PATTERN(FunctionDeclaration)
604 NOT_A_PATTERN(FunctionLiteral)
605 NOT_A_PATTERN(IfStatement)
606 NOT_A_PATTERN(ImportDeclaration)
607 NOT_A_PATTERN(Literal)
608 NOT_A_PATTERN(NativeFunctionLiteral)
609 NOT_A_PATTERN(RegExpLiteral)
610 NOT_A_PATTERN(ReturnStatement)
611 NOT_A_PATTERN(SloppyBlockFunctionStatement)
612 NOT_A_PATTERN(Spread)
613 NOT_A_PATTERN(SuperPropertyReference)
614 NOT_A_PATTERN(SuperCallReference)
615 NOT_A_PATTERN(SwitchStatement)
616 NOT_A_PATTERN(ThisFunction)
617 NOT_A_PATTERN(Throw)
618 NOT_A_PATTERN(TryCatchStatement)
619 NOT_A_PATTERN(TryFinallyStatement)
620 NOT_A_PATTERN(UnaryOperation)
621 NOT_A_PATTERN(VariableDeclaration)
622 NOT_A_PATTERN(WhileStatement)
623 NOT_A_PATTERN(WithStatement)
624 NOT_A_PATTERN(Yield)
625 
626 #undef NOT_A_PATTERN
627 }  // namespace internal
628 }  // namespace v8
629