blob: f3d9bb02a33bec518052372f713aec08ea3ef756 [file] [log] [blame]
Ben Murdoch014dc512016-03-22 12:00:34 +00001// 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
10namespace v8 {
11
12namespace internal {
13
14void Parser::PatternRewriter::DeclareAndInitializeVariables(
Ben Murdochf3b273f2017-01-17 12:11:28 +000015 Parser* parser, Block* block,
16 const DeclarationDescriptor* declaration_descriptor,
Ben Murdoch014dc512016-03-22 12:00:34 +000017 const DeclarationParsingResult::Declaration* declaration,
18 ZoneList<const AstRawString*>* names, bool* ok) {
19 PatternRewriter rewriter;
20
Ben Murdoch3b9bc312016-06-02 14:46:10 +010021 DCHECK(block->ignore_completion_value());
22
Ben Murdoch014dc512016-03-22 12:00:34 +000023 rewriter.scope_ = declaration_descriptor->scope;
Ben Murdochf3b273f2017-01-17 12:11:28 +000024 rewriter.parser_ = parser;
Ben Murdoch014dc512016-03-22 12:00:34 +000025 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
38void Parser::PatternRewriter::RewriteDestructuringAssignment(
Ben Murdoch109988c2016-05-18 11:27:45 +010039 Parser* parser, RewritableExpression* to_rewrite, Scope* scope) {
Ben Murdochf3b273f2017-01-17 12:11:28 +000040 DCHECK(!scope->HasBeenRemoved());
Ben Murdoch014dc512016-03-22 12:00:34 +000041 DCHECK(!to_rewrite->is_rewritten());
42
43 bool ok = true;
Ben Murdochf3b273f2017-01-17 12:11:28 +000044
45 PatternRewriter rewriter;
Ben Murdoch014dc512016-03-22 12:00:34 +000046 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
61Expression* Parser::PatternRewriter::RewriteDestructuringAssignment(
62 Parser* parser, Assignment* assignment, Scope* scope) {
63 DCHECK_NOT_NULL(assignment);
64 DCHECK_EQ(Token::ASSIGN, assignment->op());
Ben Murdoch109988c2016-05-18 11:27:45 +010065 auto to_rewrite = parser->factory()->NewRewritableExpression(assignment);
Ben Murdoch014dc512016-03-22 12:00:34 +000066 RewriteDestructuringAssignment(parser, to_rewrite, scope);
67 return to_rewrite->expression();
68}
69
70
Ben Murdoch014dc512016-03-22 12:00:34 +000071Parser::PatternRewriter::PatternContext
72Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
73 PatternContext old_context = context();
Ben Murdoch109988c2016-05-18 11:27:45 +010074 // 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()) {
Ben Murdoch014dc512016-03-22 12:00:34 +000079 set_context(ASSIGNMENT);
80 }
81 return old_context;
82}
83
84
85Parser::PatternRewriter::PatternContext
86Parser::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 =
Ben Murdoch109988c2016-05-18 11:27:45 +010091 node->IsRewritableExpression() &&
92 !node->AsRewritableExpression()->is_rewritten();
Ben Murdoch014dc512016-03-22 12:00:34 +000093 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
111void 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).
Ben Murdoch014dc512016-03-22 12:00:34 +0000134 const AstRawString* name = pattern->raw_name();
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000135 VariableProxy* proxy =
136 factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position());
Ben Murdoch014dc512016-03-22 12:00:34 +0000137 Declaration* declaration = factory()->NewVariableDeclaration(
Ben Murdochf91f0612016-11-29 16:50:11 +0000138 proxy, descriptor_->scope, descriptor_->declaration_pos);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000139 Variable* var = parser_->Declare(
140 declaration, descriptor_->declaration_kind, descriptor_->mode,
141 Variable::DefaultInitializationFlag(descriptor_->mode), ok_,
142 descriptor_->hoist_scope);
Ben Murdoch014dc512016-03-22 12:00:34 +0000143 if (!*ok_) return;
144 DCHECK_NOT_NULL(var);
Ben Murdochf91f0612016-11-29 16:50:11 +0000145 DCHECK(proxy->is_resolved());
146 DCHECK(initializer_position_ != kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000147 var->set_initializer_position(initializer_position_);
148
Ben Murdochf91f0612016-11-29 16:50:11 +0000149 // 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.
Ben Murdoch014dc512016-03-22 12:00:34 +0000152 Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode)
153 ? descriptor_->scope
Ben Murdochf91f0612016-11-29 16:50:11 +0000154 : descriptor_->scope->GetDeclarationScope();
155 if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000156 parser_->ReportMessage(MessageTemplate::kTooManyVariables);
157 *ok_ = false;
158 return;
159 }
160 if (names_) {
161 names_->Add(name, zone());
162 }
163
Ben Murdochf91f0612016-11-29 16:50:11 +0000164 // If there's no initializer, we're done.
165 if (value == nullptr) return;
166
167 // A declaration of the form:
Ben Murdoch014dc512016-03-22 12:00:34 +0000168 //
169 // var v = x;
170 //
171 // is syntactic sugar for:
172 //
173 // var v; v = x;
174 //
Ben Murdochf91f0612016-11-29 16:50:11 +0000175 // 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;
Ben Murdoch014dc512016-03-22 12:00:34 +0000180
Ben Murdochf91f0612016-11-29 16:50:11 +0000181 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.
Ben Murdoch014dc512016-03-22 12:00:34 +0000200
Ben Murdoch014dc512016-03-22 12:00:34 +0000201 ZoneList<Expression*>* arguments =
202 new (zone()) ZoneList<Expression*>(3, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000203 arguments->Add(
204 factory()->NewStringLiteral(name, descriptor_->declaration_pos),
205 zone());
Ben Murdochf91f0612016-11-29 16:50:11 +0000206 arguments->Add(factory()->NewNumberLiteral(var_init_scope->language_mode(),
207 kNoSourcePosition),
208 zone());
209 arguments->Add(value, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000210
Ben Murdochf91f0612016-11-29 16:50:11 +0000211 CallRuntime* initialize = factory()->NewCallRuntime(
212 Runtime::kInitializeVarGlobal, arguments, value->position());
213 block_->statements()->Add(
214 factory()->NewExpressionStatement(initialize, initialize->position()),
215 zone());
216 } else {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100217 // For 'let' and 'const' declared variables the initialization always
218 // assigns to the declared variable.
Ben Murdochf91f0612016-11-29 16:50:11 +0000219 // 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 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000226 // Add break location for destructured sub-pattern.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100227 int pos = IsSubPattern() ? pattern->position() : value->position();
Ben Murdoch014dc512016-03-22 12:00:34 +0000228 Assignment* assignment =
229 factory()->NewAssignment(Token::INIT, proxy, value, pos);
230 block_->statements()->Add(
231 factory()->NewExpressionStatement(assignment, pos), zone());
232 }
233}
234
235
236Variable* 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,
Ben Murdochf91f0612016-11-29 16:50:11 +0000241 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000242
243 block_->statements()->Add(
Ben Murdochf91f0612016-11-29 16:50:11 +0000244 factory()->NewExpressionStatement(assignment, kNoSourcePosition),
Ben Murdoch014dc512016-03-22 12:00:34 +0000245 zone());
246 }
247 return temp;
248}
249
250
Ben Murdoch109988c2016-05-18 11:27:45 +0100251void Parser::PatternRewriter::VisitRewritableExpression(
252 RewritableExpression* node) {
253 // If this is not a destructuring assignment...
Ben Murdochf3b273f2017-01-17 12:11:28 +0000254 if (!IsAssignmentContext()) {
Ben Murdoch109988c2016-05-18 11:27:45 +0100255 // Mark the node as rewritten to prevent redundant rewriting, and
Ben Murdoch014dc512016-03-22 12:00:34 +0000256 // perform BindingPattern rewriting
257 DCHECK(!node->is_rewritten());
258 node->Rewrite(node->expression());
Ben Murdochf91f0612016-11-29 16:50:11 +0000259 return Visit(node->expression());
Ben Murdochf3b273f2017-01-17 12:11:28 +0000260 } else if (!node->expression()->IsAssignment()) {
261 return Visit(node->expression());
Ben Murdoch014dc512016-03-22 12:00:34 +0000262 }
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),
Ben Murdochf91f0612016-11-29 16:50:11 +0000281 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000282 value = factory()->NewConditional(is_undefined, initializer,
283 factory()->NewVariableProxy(temp_var),
Ben Murdochf91f0612016-11-29 16:50:11 +0000284 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000285 }
286
287 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
288 int pos = assign->position();
289 Block* old_block = block_;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100290 block_ = factory()->NewBlock(nullptr, 8, true, pos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000291 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
Ben Murdochf91f0612016-11-29 16:50:11 +0000313// 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.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100317void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) {
318 if (!IsBindingContext()) return;
319 if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return;
Ben Murdochf91f0612016-11-29 16:50:11 +0000320 if (!scope()->is_block_scope()) return;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100321
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100322 DCHECK(scope()->is_declaration_scope());
Ben Murdochf91f0612016-11-29 16:50:11 +0000323 DCHECK(scope()->outer_scope()->is_function_scope());
324 DCHECK(scope()->calls_sloppy_eval());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100325
Ben Murdochf91f0612016-11-29 16:50:11 +0000326 ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100327}
Ben Murdoch014dc512016-03-22 12:00:34 +0000328
329void 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());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100337
338 // Computed property names contain expressions which might require
339 // scope rewriting.
340 if (!property->key()->IsLiteral()) RewriteParameterScopes(property->key());
341
Ben Murdoch014dc512016-03-22 12:00:34 +0000342 RecurseIntoSubpattern(
343 property->value(),
344 factory()->NewProperty(factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000345 property->key(), kNoSourcePosition));
Ben Murdoch014dc512016-03-22 12:00:34 +0000346 set_context(context);
347 }
348}
349
350
351void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
352 Variable* temp_var = nullptr;
353 VisitObjectLiteral(node, &temp_var);
354}
355
356
357void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
358 Variable** temp_var) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100359 DCHECK(block_->ignore_completion_value());
360
Ben Murdoch014dc512016-03-22 12:00:34 +0000361 auto temp = *temp_var = CreateTempVar(current_value_);
Ben Murdoch014dc512016-03-22 12:00:34 +0000362 auto iterator = CreateTempVar(parser_->GetIterator(
Ben Murdochf3b273f2017-01-17 12:11:28 +0000363 factory()->NewVariableProxy(temp), kNoSourcePosition));
Ben Murdochf91f0612016-11-29 16:50:11 +0000364 auto done =
365 CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
Ben Murdoch014dc512016-03-22 12:00:34 +0000366 auto result = CreateTempVar();
367 auto v = CreateTempVar();
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100368 auto completion = CreateTempVar();
Ben Murdochf91f0612016-11-29 16:50:11 +0000369 auto nopos = kNoSourcePosition;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100370
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_;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100377 block_ = factory()->NewBlock(nullptr, 8, true, nopos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000378
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);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100387
Ben Murdoch014dc512016-03-22 12:00:34 +0000388 // if (!done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100389 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch014dc512016-03-22 12:00:34 +0000390 // result = IteratorNext(iterator);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100391 // if (result.done) {
392 // v = undefined;
393 // } else {
394 // v = result.value;
395 // done = false;
396 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000397 // }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100398 Statement* if_not_done;
399 {
400 auto result_done = factory()->NewProperty(
401 factory()->NewVariableProxy(result),
402 factory()->NewStringLiteral(ast_value_factory()->done_string(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000403 kNoSourcePosition),
404 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000405
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100406 auto assign_undefined = factory()->NewAssignment(
407 Token::ASSIGN, factory()->NewVariableProxy(v),
Ben Murdochf91f0612016-11-29 16:50:11 +0000408 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000409
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100410 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(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000415 kNoSourcePosition),
416 kNoSourcePosition),
417 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100418
419 auto unset_done = factory()->NewAssignment(
420 Token::ASSIGN, factory()->NewVariableProxy(done),
Ben Murdochf91f0612016-11-29 16:50:11 +0000421 factory()->NewBooleanLiteral(false, kNoSourcePosition),
422 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100423
424 auto inner_else =
Ben Murdochf91f0612016-11-29 16:50:11 +0000425 factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100426 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 =
Ben Murdochf91f0612016-11-29 16:50:11 +0000437 factory()->NewBlock(nullptr, 3, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100438 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,
Ben Murdochf91f0612016-11-29 16:50:11 +0000449 kNoSourcePosition),
450 kNoSourcePosition),
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100451 zone());
452 next_block->statements()->Add(inner_if, zone());
453
454 if_not_done = factory()->NewIfStatement(
Ben Murdochf91f0612016-11-29 16:50:11 +0000455 factory()->NewUnaryOperation(
456 Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
457 next_block, factory()->NewEmptyStatement(kNoSourcePosition),
458 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100459 }
460 block_->statements()->Add(if_not_done, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000461
462 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100463 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100464 // 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
Ben Murdoch014dc512016-03-22 12:00:34 +0000473 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100474
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100475 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100476 // 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 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000484 }
485 set_context(context);
486 }
487
488 if (spread != nullptr) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100489 // A spread can only occur as the last component. It is not handled by
490 // RecurseIntoSubpattern above.
Ben Murdoch014dc512016-03-22 12:00:34 +0000491
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100492 // let array = [];
493 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100494 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100495 // result = IteratorNext(iterator);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100496 // if (!result.done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100497 // %AppendElement(array, result.value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100498 // done = false;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100499 // }
500 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000501
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100502 // 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.
Ben Murdochf91f0612016-11-29 16:50:11 +0000510 node->literal_index(), kNoSourcePosition));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100511 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000512
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100513 // 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
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100520 // result = IteratorNext(iterator);
521 Statement* get_next = factory()->NewExpressionStatement(
522 parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
523 result, nopos),
524 nopos);
525
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100526 // %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
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100542 // 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;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100551 {
552 Expression* result_done =
553 factory()->NewProperty(factory()->NewVariableProxy(result),
554 factory()->NewStringLiteral(
555 ast_value_factory()->done_string(), nopos),
556 nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100557
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);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100565 }
566
567 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100568 // #set_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100569 // #get_next;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100570 // #maybe_append_and_unset_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100571 // }
572 WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
573 {
574 Expression* condition = factory()->NewUnaryOperation(
575 Token::NOT, factory()->NewVariableProxy(done), nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100576 Block* body = factory()->NewBlock(nullptr, 3, true, nopos);
577 body->statements()->Add(set_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100578 body->statements()->Add(get_next, zone());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100579 body->statements()->Add(maybe_append_and_unset_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100580 loop->Initialize(condition, body);
581 }
582
583 block_->statements()->Add(loop, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000584 RecurseIntoSubpattern(spread->expression(),
585 factory()->NewVariableProxy(array));
586 }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100587
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100588 Expression* closing_condition = factory()->NewUnaryOperation(
589 Token::NOT, factory()->NewVariableProxy(done), nopos);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000590
591 parser_->FinalizeIteratorUse(scope(), completion, closing_condition, iterator,
592 block_, target);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100593 block_ = target;
Ben Murdoch014dc512016-03-22 12:00:34 +0000594}
595
596
597void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
598 Variable* temp_var = nullptr;
599 VisitArrayLiteral(node, &temp_var);
600}
601
602
603void 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),
Ben Murdochf91f0612016-11-29 16:50:11 +0000617 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000618 value = factory()->NewConditional(is_undefined, initializer,
619 factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000620 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000621 }
622
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100623 // Initializer may have been parsed in the wrong scope.
624 RewriteParameterScopes(initializer);
Ben Murdoch014dc512016-03-22 12:00:34 +0000625
626 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
627 RecurseIntoSubpattern(node->target(), value);
628 set_context(old_context);
629}
630
631
632// =============== AssignmentPattern only ==================
633
634void 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(
Ben Murdochf91f0612016-11-29 16:50:11 +0000642 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000643}
644
645
646// =============== UNREACHABLE =============================
647
Ben Murdoch014dc512016-03-22 12:00:34 +0000648#define NOT_A_PATTERN(Node) \
649 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
650 UNREACHABLE(); \
651 }
652
653NOT_A_PATTERN(BinaryOperation)
654NOT_A_PATTERN(Block)
655NOT_A_PATTERN(BreakStatement)
656NOT_A_PATTERN(Call)
657NOT_A_PATTERN(CallNew)
658NOT_A_PATTERN(CallRuntime)
659NOT_A_PATTERN(CaseClause)
660NOT_A_PATTERN(ClassLiteral)
661NOT_A_PATTERN(CompareOperation)
662NOT_A_PATTERN(Conditional)
663NOT_A_PATTERN(ContinueStatement)
664NOT_A_PATTERN(CountOperation)
665NOT_A_PATTERN(DebuggerStatement)
666NOT_A_PATTERN(DoExpression)
667NOT_A_PATTERN(DoWhileStatement)
668NOT_A_PATTERN(EmptyStatement)
669NOT_A_PATTERN(EmptyParentheses)
Ben Murdoch014dc512016-03-22 12:00:34 +0000670NOT_A_PATTERN(ExpressionStatement)
671NOT_A_PATTERN(ForInStatement)
672NOT_A_PATTERN(ForOfStatement)
673NOT_A_PATTERN(ForStatement)
674NOT_A_PATTERN(FunctionDeclaration)
675NOT_A_PATTERN(FunctionLiteral)
676NOT_A_PATTERN(IfStatement)
Ben Murdoch014dc512016-03-22 12:00:34 +0000677NOT_A_PATTERN(Literal)
678NOT_A_PATTERN(NativeFunctionLiteral)
679NOT_A_PATTERN(RegExpLiteral)
680NOT_A_PATTERN(ReturnStatement)
681NOT_A_PATTERN(SloppyBlockFunctionStatement)
682NOT_A_PATTERN(Spread)
683NOT_A_PATTERN(SuperPropertyReference)
684NOT_A_PATTERN(SuperCallReference)
685NOT_A_PATTERN(SwitchStatement)
686NOT_A_PATTERN(ThisFunction)
687NOT_A_PATTERN(Throw)
688NOT_A_PATTERN(TryCatchStatement)
689NOT_A_PATTERN(TryFinallyStatement)
690NOT_A_PATTERN(UnaryOperation)
691NOT_A_PATTERN(VariableDeclaration)
692NOT_A_PATTERN(WhileStatement)
693NOT_A_PATTERN(WithStatement)
694NOT_A_PATTERN(Yield)
695
696#undef NOT_A_PATTERN
697} // namespace internal
698} // namespace v8