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