blob: 7898f872447c0e20215077d8fe33b080cec7792e [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
71bool Parser::PatternRewriter::IsAssignmentContext(PatternContext c) const {
72 return c == ASSIGNMENT || c == ASSIGNMENT_INITIALIZER;
73}
74
75
76bool Parser::PatternRewriter::IsBindingContext(PatternContext c) const {
77 return c == BINDING || c == INITIALIZER;
78}
79
80
81Parser::PatternRewriter::PatternContext
82Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
83 PatternContext old_context = context();
Ben Murdoch109988c2016-05-18 11:27:45 +010084 // AssignmentExpressions may occur in the Initializer position of a
85 // SingleNameBinding. Such expressions should not prompt a change in the
86 // pattern's context.
87 if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN &&
88 !IsInitializerContext()) {
Ben Murdoch014dc512016-03-22 12:00:34 +000089 set_context(ASSIGNMENT);
90 }
91 return old_context;
92}
93
94
95Parser::PatternRewriter::PatternContext
96Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) {
97 // Set appropriate initializer context for BindingElement and
98 // AssignmentElement nodes
99 PatternContext old_context = context();
100 bool is_destructuring_assignment =
Ben Murdoch109988c2016-05-18 11:27:45 +0100101 node->IsRewritableExpression() &&
102 !node->AsRewritableExpression()->is_rewritten();
Ben Murdoch014dc512016-03-22 12:00:34 +0000103 bool is_assignment =
104 node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN;
105 if (is_destructuring_assignment || is_assignment) {
106 switch (old_context) {
107 case BINDING:
108 set_context(INITIALIZER);
109 break;
110 case ASSIGNMENT:
111 set_context(ASSIGNMENT_INITIALIZER);
112 break;
113 default:
114 break;
115 }
116 }
117 return old_context;
118}
119
120
121void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
122 Expression* value = current_value_;
123
124 if (IsAssignmentContext()) {
125 // In an assignment context, simply perform the assignment
126 Assignment* assignment = factory()->NewAssignment(
127 Token::ASSIGN, pattern, value, pattern->position());
128 block_->statements()->Add(
129 factory()->NewExpressionStatement(assignment, pattern->position()),
130 zone());
131 return;
132 }
133
134 descriptor_->scope->RemoveUnresolved(pattern);
135
136 // Declare variable.
137 // Note that we *always* must treat the initial value via a separate init
138 // assignment for variables and constants because the value must be assigned
139 // when the variable is encountered in the source. But the variable/constant
140 // is declared (and set to 'undefined') upon entering the function within
141 // which the variable or constant is declared. Only function variables have
142 // an initial value in the declaration (because they are initialized upon
143 // entering the function).
Ben Murdoch014dc512016-03-22 12:00:34 +0000144 const AstRawString* name = pattern->raw_name();
Ben Murdochf3b273f2017-01-17 12:11:28 +0000145 VariableProxy* proxy = factory()->NewVariableProxy(
146 name, NORMAL_VARIABLE, parser_->scanner()->location().beg_pos,
Ben Murdochf91f0612016-11-29 16:50:11 +0000147 parser_->scanner()->location().end_pos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000148 Declaration* declaration = factory()->NewVariableDeclaration(
Ben Murdochf91f0612016-11-29 16:50:11 +0000149 proxy, descriptor_->scope, descriptor_->declaration_pos);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000150 Variable* var = parser_->Declare(
151 declaration, descriptor_->declaration_kind, descriptor_->mode,
152 Variable::DefaultInitializationFlag(descriptor_->mode), ok_,
153 descriptor_->hoist_scope);
Ben Murdoch014dc512016-03-22 12:00:34 +0000154 if (!*ok_) return;
155 DCHECK_NOT_NULL(var);
Ben Murdochf91f0612016-11-29 16:50:11 +0000156 DCHECK(proxy->is_resolved());
157 DCHECK(initializer_position_ != kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000158 var->set_initializer_position(initializer_position_);
159
Ben Murdochf91f0612016-11-29 16:50:11 +0000160 // TODO(adamk): This should probably be checking hoist_scope.
161 // Move it to Parser::Declare() to make it easier to test
162 // the right scope.
Ben Murdoch014dc512016-03-22 12:00:34 +0000163 Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode)
164 ? descriptor_->scope
Ben Murdochf91f0612016-11-29 16:50:11 +0000165 : descriptor_->scope->GetDeclarationScope();
166 if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000167 parser_->ReportMessage(MessageTemplate::kTooManyVariables);
168 *ok_ = false;
169 return;
170 }
171 if (names_) {
172 names_->Add(name, zone());
173 }
174
Ben Murdochf91f0612016-11-29 16:50:11 +0000175 // If there's no initializer, we're done.
176 if (value == nullptr) return;
177
178 // A declaration of the form:
Ben Murdoch014dc512016-03-22 12:00:34 +0000179 //
180 // var v = x;
181 //
182 // is syntactic sugar for:
183 //
184 // var v; v = x;
185 //
Ben Murdochf91f0612016-11-29 16:50:11 +0000186 // In particular, we need to re-lookup 'v' as it may be a different
187 // 'v' than the 'v' in the declaration (e.g., if we are inside a
188 // 'with' statement or 'catch' block). Global var declarations
189 // also need special treatment.
190 Scope* var_init_scope = descriptor_->scope;
Ben Murdoch014dc512016-03-22 12:00:34 +0000191
Ben Murdochf91f0612016-11-29 16:50:11 +0000192 if (descriptor_->mode == VAR && var_init_scope->is_script_scope()) {
193 // Global variable declarations must be compiled in a specific
194 // way. When the script containing the global variable declaration
195 // is entered, the global variable must be declared, so that if it
196 // doesn't exist (on the global object itself, see ES5 errata) it
197 // gets created with an initial undefined value. This is handled
198 // by the declarations part of the function representing the
199 // top-level global code; see Runtime::DeclareGlobalVariable. If
200 // it already exists (in the object or in a prototype), it is
201 // *not* touched until the variable declaration statement is
202 // executed.
203 //
204 // Executing the variable declaration statement will always
205 // guarantee to give the global object an own property.
206 // This way, global variable declarations can shadow
207 // properties in the prototype chain, but only after the variable
208 // declaration statement has been executed. This is important in
209 // browsers where the global object (window) has lots of
210 // properties defined in prototype objects.
Ben Murdoch014dc512016-03-22 12:00:34 +0000211
Ben Murdoch014dc512016-03-22 12:00:34 +0000212 ZoneList<Expression*>* arguments =
213 new (zone()) ZoneList<Expression*>(3, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000214 arguments->Add(
215 factory()->NewStringLiteral(name, descriptor_->declaration_pos),
216 zone());
Ben Murdochf91f0612016-11-29 16:50:11 +0000217 arguments->Add(factory()->NewNumberLiteral(var_init_scope->language_mode(),
218 kNoSourcePosition),
219 zone());
220 arguments->Add(value, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000221
Ben Murdochf91f0612016-11-29 16:50:11 +0000222 CallRuntime* initialize = factory()->NewCallRuntime(
223 Runtime::kInitializeVarGlobal, arguments, value->position());
224 block_->statements()->Add(
225 factory()->NewExpressionStatement(initialize, initialize->position()),
226 zone());
227 } else {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100228 // For 'let' and 'const' declared variables the initialization always
229 // assigns to the declared variable.
Ben Murdochf91f0612016-11-29 16:50:11 +0000230 // But for var declarations we need to do a new lookup.
231 if (descriptor_->mode == VAR) {
232 proxy = var_init_scope->NewUnresolved(factory(), name);
233 } else {
234 DCHECK_NOT_NULL(proxy);
235 DCHECK_NOT_NULL(proxy->var());
236 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000237 // Add break location for destructured sub-pattern.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100238 int pos = IsSubPattern() ? pattern->position() : value->position();
Ben Murdoch014dc512016-03-22 12:00:34 +0000239 Assignment* assignment =
240 factory()->NewAssignment(Token::INIT, proxy, value, pos);
241 block_->statements()->Add(
242 factory()->NewExpressionStatement(assignment, pos), zone());
243 }
244}
245
246
247Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
248 auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
249 if (value != nullptr) {
250 auto assignment = factory()->NewAssignment(
251 Token::ASSIGN, factory()->NewVariableProxy(temp), value,
Ben Murdochf91f0612016-11-29 16:50:11 +0000252 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000253
254 block_->statements()->Add(
Ben Murdochf91f0612016-11-29 16:50:11 +0000255 factory()->NewExpressionStatement(assignment, kNoSourcePosition),
Ben Murdoch014dc512016-03-22 12:00:34 +0000256 zone());
257 }
258 return temp;
259}
260
261
Ben Murdoch109988c2016-05-18 11:27:45 +0100262void Parser::PatternRewriter::VisitRewritableExpression(
263 RewritableExpression* node) {
264 // If this is not a destructuring assignment...
Ben Murdochf3b273f2017-01-17 12:11:28 +0000265 if (!IsAssignmentContext()) {
Ben Murdoch109988c2016-05-18 11:27:45 +0100266 // Mark the node as rewritten to prevent redundant rewriting, and
Ben Murdoch014dc512016-03-22 12:00:34 +0000267 // perform BindingPattern rewriting
268 DCHECK(!node->is_rewritten());
269 node->Rewrite(node->expression());
Ben Murdochf91f0612016-11-29 16:50:11 +0000270 return Visit(node->expression());
Ben Murdochf3b273f2017-01-17 12:11:28 +0000271 } else if (!node->expression()->IsAssignment()) {
272 return Visit(node->expression());
Ben Murdoch014dc512016-03-22 12:00:34 +0000273 }
274
275 if (node->is_rewritten()) return;
276 DCHECK(IsAssignmentContext());
277 Assignment* assign = node->expression()->AsAssignment();
278 DCHECK_NOT_NULL(assign);
279 DCHECK_EQ(Token::ASSIGN, assign->op());
280
281 auto initializer = assign->value();
282 auto value = initializer;
283
284 if (IsInitializerContext()) {
285 // let {<pattern> = <init>} = <value>
286 // becomes
287 // temp = <value>;
288 // <pattern> = temp === undefined ? <init> : temp;
289 auto temp_var = CreateTempVar(current_value_);
290 Expression* is_undefined = factory()->NewCompareOperation(
291 Token::EQ_STRICT, factory()->NewVariableProxy(temp_var),
Ben Murdochf91f0612016-11-29 16:50:11 +0000292 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000293 value = factory()->NewConditional(is_undefined, initializer,
294 factory()->NewVariableProxy(temp_var),
Ben Murdochf91f0612016-11-29 16:50:11 +0000295 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000296 }
297
298 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
299 int pos = assign->position();
300 Block* old_block = block_;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100301 block_ = factory()->NewBlock(nullptr, 8, true, pos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000302 Variable* temp = nullptr;
303 Expression* pattern = assign->target();
304 Expression* old_value = current_value_;
305 current_value_ = value;
306 if (pattern->IsObjectLiteral()) {
307 VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
308 } else {
309 DCHECK(pattern->IsArrayLiteral());
310 VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
311 }
312 DCHECK_NOT_NULL(temp);
313 current_value_ = old_value;
314 Expression* expr = factory()->NewDoExpression(block_, temp, pos);
315 node->Rewrite(expr);
316 block_ = old_block;
317 if (block_) {
318 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
319 zone());
320 }
321 return set_context(old_context);
322}
323
Ben Murdochf91f0612016-11-29 16:50:11 +0000324// When an extra declaration scope needs to be inserted to account for
325// a sloppy eval in a default parameter or function body, the expressions
326// needs to be in that new inner scope which was added after initial
327// parsing.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100328void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) {
329 if (!IsBindingContext()) return;
330 if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return;
Ben Murdochf91f0612016-11-29 16:50:11 +0000331 if (!scope()->is_block_scope()) return;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100332
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100333 DCHECK(scope()->is_declaration_scope());
Ben Murdochf91f0612016-11-29 16:50:11 +0000334 DCHECK(scope()->outer_scope()->is_function_scope());
335 DCHECK(scope()->calls_sloppy_eval());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100336
Ben Murdochf91f0612016-11-29 16:50:11 +0000337 ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100338}
Ben Murdoch014dc512016-03-22 12:00:34 +0000339
340void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
341 Variable** temp_var) {
342 auto temp = *temp_var = CreateTempVar(current_value_);
343
344 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
345
346 for (ObjectLiteralProperty* property : *pattern->properties()) {
347 PatternContext context = SetInitializerContextIfNeeded(property->value());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100348
349 // Computed property names contain expressions which might require
350 // scope rewriting.
351 if (!property->key()->IsLiteral()) RewriteParameterScopes(property->key());
352
Ben Murdoch014dc512016-03-22 12:00:34 +0000353 RecurseIntoSubpattern(
354 property->value(),
355 factory()->NewProperty(factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000356 property->key(), kNoSourcePosition));
Ben Murdoch014dc512016-03-22 12:00:34 +0000357 set_context(context);
358 }
359}
360
361
362void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
363 Variable* temp_var = nullptr;
364 VisitObjectLiteral(node, &temp_var);
365}
366
367
368void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
369 Variable** temp_var) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100370 DCHECK(block_->ignore_completion_value());
371
Ben Murdoch014dc512016-03-22 12:00:34 +0000372 auto temp = *temp_var = CreateTempVar(current_value_);
Ben Murdoch014dc512016-03-22 12:00:34 +0000373 auto iterator = CreateTempVar(parser_->GetIterator(
Ben Murdochf3b273f2017-01-17 12:11:28 +0000374 factory()->NewVariableProxy(temp), kNoSourcePosition));
Ben Murdochf91f0612016-11-29 16:50:11 +0000375 auto done =
376 CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
Ben Murdoch014dc512016-03-22 12:00:34 +0000377 auto result = CreateTempVar();
378 auto v = CreateTempVar();
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100379 auto completion = CreateTempVar();
Ben Murdochf91f0612016-11-29 16:50:11 +0000380 auto nopos = kNoSourcePosition;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100381
382 // For the purpose of iterator finalization, we temporarily set block_ to a
383 // new block. In the main body of this function, we write to block_ (both
384 // explicitly and implicitly via recursion). At the end of the function, we
385 // wrap this new block in a try-finally statement, restore block_ to its
386 // original value, and add the try-finally statement to block_.
387 auto target = block_;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100388 block_ = factory()->NewBlock(nullptr, 8, true, nopos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000389
390 Spread* spread = nullptr;
391 for (Expression* value : *node->values()) {
392 if (value->IsSpread()) {
393 spread = value->AsSpread();
394 break;
395 }
396
397 PatternContext context = SetInitializerContextIfNeeded(value);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100398
Ben Murdoch014dc512016-03-22 12:00:34 +0000399 // if (!done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100400 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch014dc512016-03-22 12:00:34 +0000401 // result = IteratorNext(iterator);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100402 // if (result.done) {
403 // v = undefined;
404 // } else {
405 // v = result.value;
406 // done = false;
407 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000408 // }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100409 Statement* if_not_done;
410 {
411 auto result_done = factory()->NewProperty(
412 factory()->NewVariableProxy(result),
413 factory()->NewStringLiteral(ast_value_factory()->done_string(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000414 kNoSourcePosition),
415 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000416
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100417 auto assign_undefined = factory()->NewAssignment(
418 Token::ASSIGN, factory()->NewVariableProxy(v),
Ben Murdochf91f0612016-11-29 16:50:11 +0000419 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000420
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100421 auto assign_value = factory()->NewAssignment(
422 Token::ASSIGN, factory()->NewVariableProxy(v),
423 factory()->NewProperty(
424 factory()->NewVariableProxy(result),
425 factory()->NewStringLiteral(ast_value_factory()->value_string(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000426 kNoSourcePosition),
427 kNoSourcePosition),
428 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100429
430 auto unset_done = factory()->NewAssignment(
431 Token::ASSIGN, factory()->NewVariableProxy(done),
Ben Murdochf91f0612016-11-29 16:50:11 +0000432 factory()->NewBooleanLiteral(false, kNoSourcePosition),
433 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100434
435 auto inner_else =
Ben Murdochf91f0612016-11-29 16:50:11 +0000436 factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100437 inner_else->statements()->Add(
438 factory()->NewExpressionStatement(assign_value, nopos), zone());
439 inner_else->statements()->Add(
440 factory()->NewExpressionStatement(unset_done, nopos), zone());
441
442 auto inner_if = factory()->NewIfStatement(
443 result_done,
444 factory()->NewExpressionStatement(assign_undefined, nopos),
445 inner_else, nopos);
446
447 auto next_block =
Ben Murdochf91f0612016-11-29 16:50:11 +0000448 factory()->NewBlock(nullptr, 3, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100449 next_block->statements()->Add(
450 factory()->NewExpressionStatement(
451 factory()->NewAssignment(
452 Token::ASSIGN, factory()->NewVariableProxy(done),
453 factory()->NewBooleanLiteral(true, nopos), nopos),
454 nopos),
455 zone());
456 next_block->statements()->Add(
457 factory()->NewExpressionStatement(
458 parser_->BuildIteratorNextResult(
459 factory()->NewVariableProxy(iterator), result,
Ben Murdochf91f0612016-11-29 16:50:11 +0000460 kNoSourcePosition),
461 kNoSourcePosition),
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100462 zone());
463 next_block->statements()->Add(inner_if, zone());
464
465 if_not_done = factory()->NewIfStatement(
Ben Murdochf91f0612016-11-29 16:50:11 +0000466 factory()->NewUnaryOperation(
467 Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
468 next_block, factory()->NewEmptyStatement(kNoSourcePosition),
469 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100470 }
471 block_->statements()->Add(if_not_done, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000472
473 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100474 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100475 // completion = kAbruptCompletion;
476 Expression* proxy = factory()->NewVariableProxy(completion);
477 Expression* assignment = factory()->NewAssignment(
478 Token::ASSIGN, proxy,
479 factory()->NewSmiLiteral(kAbruptCompletion, nopos), nopos);
480 block_->statements()->Add(
481 factory()->NewExpressionStatement(assignment, nopos), zone());
482 }
483
Ben Murdoch014dc512016-03-22 12:00:34 +0000484 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100485
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100486 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100487 // completion = kNormalCompletion;
488 Expression* proxy = factory()->NewVariableProxy(completion);
489 Expression* assignment = factory()->NewAssignment(
490 Token::ASSIGN, proxy,
491 factory()->NewSmiLiteral(kNormalCompletion, nopos), nopos);
492 block_->statements()->Add(
493 factory()->NewExpressionStatement(assignment, nopos), zone());
494 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000495 }
496 set_context(context);
497 }
498
499 if (spread != nullptr) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100500 // A spread can only occur as the last component. It is not handled by
501 // RecurseIntoSubpattern above.
Ben Murdoch014dc512016-03-22 12:00:34 +0000502
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100503 // let array = [];
504 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100505 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100506 // result = IteratorNext(iterator);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100507 // if (!result.done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100508 // %AppendElement(array, result.value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100509 // done = false;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100510 // }
511 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000512
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100513 // let array = [];
514 Variable* array;
515 {
516 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
517 array = CreateTempVar(factory()->NewArrayLiteral(
518 empty_exprs,
519 // Reuse pattern's literal index - it is unused since there is no
520 // actual literal allocated.
Ben Murdochf91f0612016-11-29 16:50:11 +0000521 node->literal_index(), kNoSourcePosition));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100522 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000523
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100524 // done = true;
525 Statement* set_done = factory()->NewExpressionStatement(
526 factory()->NewAssignment(
527 Token::ASSIGN, factory()->NewVariableProxy(done),
528 factory()->NewBooleanLiteral(true, nopos), nopos),
529 nopos);
530
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100531 // result = IteratorNext(iterator);
532 Statement* get_next = factory()->NewExpressionStatement(
533 parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
534 result, nopos),
535 nopos);
536
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100537 // %AppendElement(array, result.value);
538 Statement* append_element;
539 {
540 auto args = new (zone()) ZoneList<Expression*>(2, zone());
541 args->Add(factory()->NewVariableProxy(array), zone());
542 args->Add(factory()->NewProperty(
543 factory()->NewVariableProxy(result),
544 factory()->NewStringLiteral(
545 ast_value_factory()->value_string(), nopos),
546 nopos),
547 zone());
548 append_element = factory()->NewExpressionStatement(
549 factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
550 nopos);
551 }
552
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100553 // done = false;
554 Statement* unset_done = factory()->NewExpressionStatement(
555 factory()->NewAssignment(
556 Token::ASSIGN, factory()->NewVariableProxy(done),
557 factory()->NewBooleanLiteral(false, nopos), nopos),
558 nopos);
559
560 // if (!result.done) { #append_element; #unset_done }
561 Statement* maybe_append_and_unset_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100562 {
563 Expression* result_done =
564 factory()->NewProperty(factory()->NewVariableProxy(result),
565 factory()->NewStringLiteral(
566 ast_value_factory()->done_string(), nopos),
567 nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100568
569 Block* then = factory()->NewBlock(nullptr, 2, true, nopos);
570 then->statements()->Add(append_element, zone());
571 then->statements()->Add(unset_done, zone());
572
573 maybe_append_and_unset_done = factory()->NewIfStatement(
574 factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
575 factory()->NewEmptyStatement(nopos), nopos);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100576 }
577
578 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100579 // #set_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100580 // #get_next;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100581 // #maybe_append_and_unset_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100582 // }
583 WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
584 {
585 Expression* condition = factory()->NewUnaryOperation(
586 Token::NOT, factory()->NewVariableProxy(done), nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100587 Block* body = factory()->NewBlock(nullptr, 3, true, nopos);
588 body->statements()->Add(set_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100589 body->statements()->Add(get_next, zone());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100590 body->statements()->Add(maybe_append_and_unset_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100591 loop->Initialize(condition, body);
592 }
593
594 block_->statements()->Add(loop, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000595 RecurseIntoSubpattern(spread->expression(),
596 factory()->NewVariableProxy(array));
597 }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100598
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100599 Expression* closing_condition = factory()->NewUnaryOperation(
600 Token::NOT, factory()->NewVariableProxy(done), nopos);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000601
602 parser_->FinalizeIteratorUse(scope(), completion, closing_condition, iterator,
603 block_, target);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100604 block_ = target;
Ben Murdoch014dc512016-03-22 12:00:34 +0000605}
606
607
608void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
609 Variable* temp_var = nullptr;
610 VisitArrayLiteral(node, &temp_var);
611}
612
613
614void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
615 // let {<pattern> = <init>} = <value>
616 // becomes
617 // temp = <value>;
618 // <pattern> = temp === undefined ? <init> : temp;
619 DCHECK_EQ(Token::ASSIGN, node->op());
620
621 auto initializer = node->value();
622 auto value = initializer;
623 auto temp = CreateTempVar(current_value_);
624
625 if (IsInitializerContext()) {
626 Expression* is_undefined = factory()->NewCompareOperation(
627 Token::EQ_STRICT, factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000628 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000629 value = factory()->NewConditional(is_undefined, initializer,
630 factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000631 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000632 }
633
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100634 // Initializer may have been parsed in the wrong scope.
635 RewriteParameterScopes(initializer);
Ben Murdoch014dc512016-03-22 12:00:34 +0000636
637 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
638 RecurseIntoSubpattern(node->target(), value);
639 set_context(old_context);
640}
641
642
643// =============== AssignmentPattern only ==================
644
645void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
646 DCHECK(IsAssignmentContext());
647 auto value = current_value_;
648
649 Assignment* assignment =
650 factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
651
652 block_->statements()->Add(
Ben Murdochf91f0612016-11-29 16:50:11 +0000653 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000654}
655
656
657// =============== UNREACHABLE =============================
658
Ben Murdoch014dc512016-03-22 12:00:34 +0000659#define NOT_A_PATTERN(Node) \
660 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
661 UNREACHABLE(); \
662 }
663
664NOT_A_PATTERN(BinaryOperation)
665NOT_A_PATTERN(Block)
666NOT_A_PATTERN(BreakStatement)
667NOT_A_PATTERN(Call)
668NOT_A_PATTERN(CallNew)
669NOT_A_PATTERN(CallRuntime)
670NOT_A_PATTERN(CaseClause)
671NOT_A_PATTERN(ClassLiteral)
672NOT_A_PATTERN(CompareOperation)
673NOT_A_PATTERN(Conditional)
674NOT_A_PATTERN(ContinueStatement)
675NOT_A_PATTERN(CountOperation)
676NOT_A_PATTERN(DebuggerStatement)
677NOT_A_PATTERN(DoExpression)
678NOT_A_PATTERN(DoWhileStatement)
679NOT_A_PATTERN(EmptyStatement)
680NOT_A_PATTERN(EmptyParentheses)
Ben Murdoch014dc512016-03-22 12:00:34 +0000681NOT_A_PATTERN(ExpressionStatement)
682NOT_A_PATTERN(ForInStatement)
683NOT_A_PATTERN(ForOfStatement)
684NOT_A_PATTERN(ForStatement)
685NOT_A_PATTERN(FunctionDeclaration)
686NOT_A_PATTERN(FunctionLiteral)
687NOT_A_PATTERN(IfStatement)
Ben Murdoch014dc512016-03-22 12:00:34 +0000688NOT_A_PATTERN(Literal)
689NOT_A_PATTERN(NativeFunctionLiteral)
690NOT_A_PATTERN(RegExpLiteral)
691NOT_A_PATTERN(ReturnStatement)
692NOT_A_PATTERN(SloppyBlockFunctionStatement)
693NOT_A_PATTERN(Spread)
694NOT_A_PATTERN(SuperPropertyReference)
695NOT_A_PATTERN(SuperCallReference)
696NOT_A_PATTERN(SwitchStatement)
697NOT_A_PATTERN(ThisFunction)
698NOT_A_PATTERN(Throw)
699NOT_A_PATTERN(TryCatchStatement)
700NOT_A_PATTERN(TryFinallyStatement)
701NOT_A_PATTERN(UnaryOperation)
702NOT_A_PATTERN(VariableDeclaration)
703NOT_A_PATTERN(WhileStatement)
704NOT_A_PATTERN(WithStatement)
705NOT_A_PATTERN(Yield)
706
707#undef NOT_A_PATTERN
708} // namespace internal
709} // namespace v8