blob: 1831a2927db40eb92d5aadbd584e2ed671f50b4e [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(
15 Block* block, const DeclarationDescriptor* declaration_descriptor,
16 const DeclarationParsingResult::Declaration* declaration,
17 ZoneList<const AstRawString*>* names, bool* ok) {
18 PatternRewriter rewriter;
19
Ben Murdoch3b9bc312016-06-02 14:46:10 +010020 DCHECK(block->ignore_completion_value());
21
Ben Murdoch014dc512016-03-22 12:00:34 +000022 rewriter.scope_ = declaration_descriptor->scope;
23 rewriter.parser_ = declaration_descriptor->parser;
24 rewriter.context_ = BINDING;
25 rewriter.pattern_ = declaration->pattern;
26 rewriter.initializer_position_ = declaration->initializer_position;
27 rewriter.block_ = block;
28 rewriter.descriptor_ = declaration_descriptor;
29 rewriter.names_ = names;
30 rewriter.ok_ = ok;
31 rewriter.recursion_level_ = 0;
32
33 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
34}
35
36
37void Parser::PatternRewriter::RewriteDestructuringAssignment(
Ben Murdoch109988c2016-05-18 11:27:45 +010038 Parser* parser, RewritableExpression* to_rewrite, Scope* scope) {
Ben Murdoch014dc512016-03-22 12:00:34 +000039 PatternRewriter rewriter;
40
41 DCHECK(!to_rewrite->is_rewritten());
42
43 bool ok = true;
44 rewriter.scope_ = scope;
45 rewriter.parser_ = parser;
46 rewriter.context_ = ASSIGNMENT;
47 rewriter.pattern_ = to_rewrite;
48 rewriter.block_ = nullptr;
49 rewriter.descriptor_ = nullptr;
50 rewriter.names_ = nullptr;
51 rewriter.ok_ = &ok;
52 rewriter.recursion_level_ = 0;
53
54 rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr);
55 DCHECK(ok);
56}
57
58
59Expression* Parser::PatternRewriter::RewriteDestructuringAssignment(
60 Parser* parser, Assignment* assignment, Scope* scope) {
61 DCHECK_NOT_NULL(assignment);
62 DCHECK_EQ(Token::ASSIGN, assignment->op());
Ben Murdoch109988c2016-05-18 11:27:45 +010063 auto to_rewrite = parser->factory()->NewRewritableExpression(assignment);
Ben Murdoch014dc512016-03-22 12:00:34 +000064 RewriteDestructuringAssignment(parser, to_rewrite, scope);
65 return to_rewrite->expression();
66}
67
68
69bool Parser::PatternRewriter::IsAssignmentContext(PatternContext c) const {
70 return c == ASSIGNMENT || c == ASSIGNMENT_INITIALIZER;
71}
72
73
74bool Parser::PatternRewriter::IsBindingContext(PatternContext c) const {
75 return c == BINDING || c == INITIALIZER;
76}
77
78
79Parser::PatternRewriter::PatternContext
80Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
81 PatternContext old_context = context();
Ben Murdoch109988c2016-05-18 11:27:45 +010082 // AssignmentExpressions may occur in the Initializer position of a
83 // SingleNameBinding. Such expressions should not prompt a change in the
84 // pattern's context.
85 if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN &&
86 !IsInitializerContext()) {
Ben Murdoch014dc512016-03-22 12:00:34 +000087 set_context(ASSIGNMENT);
88 }
89 return old_context;
90}
91
92
93Parser::PatternRewriter::PatternContext
94Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) {
95 // Set appropriate initializer context for BindingElement and
96 // AssignmentElement nodes
97 PatternContext old_context = context();
98 bool is_destructuring_assignment =
Ben Murdoch109988c2016-05-18 11:27:45 +010099 node->IsRewritableExpression() &&
100 !node->AsRewritableExpression()->is_rewritten();
Ben Murdoch014dc512016-03-22 12:00:34 +0000101 bool is_assignment =
102 node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN;
103 if (is_destructuring_assignment || is_assignment) {
104 switch (old_context) {
105 case BINDING:
106 set_context(INITIALIZER);
107 break;
108 case ASSIGNMENT:
109 set_context(ASSIGNMENT_INITIALIZER);
110 break;
111 default:
112 break;
113 }
114 }
115 return old_context;
116}
117
118
119void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
120 Expression* value = current_value_;
121
122 if (IsAssignmentContext()) {
123 // In an assignment context, simply perform the assignment
124 Assignment* assignment = factory()->NewAssignment(
125 Token::ASSIGN, pattern, value, pattern->position());
126 block_->statements()->Add(
127 factory()->NewExpressionStatement(assignment, pattern->position()),
128 zone());
129 return;
130 }
131
132 descriptor_->scope->RemoveUnresolved(pattern);
133
134 // Declare variable.
135 // Note that we *always* must treat the initial value via a separate init
136 // assignment for variables and constants because the value must be assigned
137 // when the variable is encountered in the source. But the variable/constant
138 // is declared (and set to 'undefined') upon entering the function within
139 // which the variable or constant is declared. Only function variables have
140 // an initial value in the declaration (because they are initialized upon
141 // entering the function).
142 //
143 // If we have a legacy const declaration, in an inner scope, the proxy
144 // is always bound to the declared variable (independent of possibly
145 // surrounding 'with' statements).
146 // For let/const declarations in harmony mode, we can also immediately
147 // pre-resolve the proxy because it resides in the same scope as the
148 // declaration.
149 const AstRawString* name = pattern->raw_name();
Ben Murdochf91f0612016-11-29 16:50:11 +0000150 VariableProxy* proxy = descriptor_->scope->NewUnresolved(
151 factory(), name, parser_->scanner()->location().beg_pos,
152 parser_->scanner()->location().end_pos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000153 Declaration* declaration = factory()->NewVariableDeclaration(
Ben Murdochf91f0612016-11-29 16:50:11 +0000154 proxy, descriptor_->scope, descriptor_->declaration_pos);
155 Variable* var = parser_->Declare(declaration, descriptor_->declaration_kind,
156 descriptor_->mode,
157 DefaultInitializationFlag(descriptor_->mode),
158 ok_, descriptor_->hoist_scope);
Ben Murdoch014dc512016-03-22 12:00:34 +0000159 if (!*ok_) return;
160 DCHECK_NOT_NULL(var);
Ben Murdochf91f0612016-11-29 16:50:11 +0000161 DCHECK(proxy->is_resolved());
162 DCHECK(initializer_position_ != kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000163 var->set_initializer_position(initializer_position_);
164
Ben Murdochf91f0612016-11-29 16:50:11 +0000165 // TODO(adamk): This should probably be checking hoist_scope.
166 // Move it to Parser::Declare() to make it easier to test
167 // the right scope.
Ben Murdoch014dc512016-03-22 12:00:34 +0000168 Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode)
169 ? descriptor_->scope
Ben Murdochf91f0612016-11-29 16:50:11 +0000170 : descriptor_->scope->GetDeclarationScope();
171 if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000172 parser_->ReportMessage(MessageTemplate::kTooManyVariables);
173 *ok_ = false;
174 return;
175 }
176 if (names_) {
177 names_->Add(name, zone());
178 }
179
Ben Murdochf91f0612016-11-29 16:50:11 +0000180 // If there's no initializer, we're done.
181 if (value == nullptr) return;
182
183 // A declaration of the form:
Ben Murdoch014dc512016-03-22 12:00:34 +0000184 //
185 // var v = x;
186 //
187 // is syntactic sugar for:
188 //
189 // var v; v = x;
190 //
Ben Murdochf91f0612016-11-29 16:50:11 +0000191 // In particular, we need to re-lookup 'v' as it may be a different
192 // 'v' than the 'v' in the declaration (e.g., if we are inside a
193 // 'with' statement or 'catch' block). Global var declarations
194 // also need special treatment.
195 Scope* var_init_scope = descriptor_->scope;
Ben Murdoch014dc512016-03-22 12:00:34 +0000196
Ben Murdochf91f0612016-11-29 16:50:11 +0000197 if (descriptor_->mode == VAR && var_init_scope->is_script_scope()) {
198 // Global variable declarations must be compiled in a specific
199 // way. When the script containing the global variable declaration
200 // is entered, the global variable must be declared, so that if it
201 // doesn't exist (on the global object itself, see ES5 errata) it
202 // gets created with an initial undefined value. This is handled
203 // by the declarations part of the function representing the
204 // top-level global code; see Runtime::DeclareGlobalVariable. If
205 // it already exists (in the object or in a prototype), it is
206 // *not* touched until the variable declaration statement is
207 // executed.
208 //
209 // Executing the variable declaration statement will always
210 // guarantee to give the global object an own property.
211 // This way, global variable declarations can shadow
212 // properties in the prototype chain, but only after the variable
213 // declaration statement has been executed. This is important in
214 // browsers where the global object (window) has lots of
215 // properties defined in prototype objects.
Ben Murdoch014dc512016-03-22 12:00:34 +0000216
Ben Murdoch014dc512016-03-22 12:00:34 +0000217 ZoneList<Expression*>* arguments =
218 new (zone()) ZoneList<Expression*>(3, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000219 arguments->Add(
220 factory()->NewStringLiteral(name, descriptor_->declaration_pos),
221 zone());
Ben Murdochf91f0612016-11-29 16:50:11 +0000222 arguments->Add(factory()->NewNumberLiteral(var_init_scope->language_mode(),
223 kNoSourcePosition),
224 zone());
225 arguments->Add(value, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000226
Ben Murdochf91f0612016-11-29 16:50:11 +0000227 CallRuntime* initialize = factory()->NewCallRuntime(
228 Runtime::kInitializeVarGlobal, arguments, value->position());
229 block_->statements()->Add(
230 factory()->NewExpressionStatement(initialize, initialize->position()),
231 zone());
232 } else {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100233 // For 'let' and 'const' declared variables the initialization always
234 // assigns to the declared variable.
Ben Murdochf91f0612016-11-29 16:50:11 +0000235 // But for var declarations we need to do a new lookup.
236 if (descriptor_->mode == VAR) {
237 proxy = var_init_scope->NewUnresolved(factory(), name);
238 } else {
239 DCHECK_NOT_NULL(proxy);
240 DCHECK_NOT_NULL(proxy->var());
241 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000242 // Add break location for destructured sub-pattern.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100243 int pos = IsSubPattern() ? pattern->position() : value->position();
Ben Murdoch014dc512016-03-22 12:00:34 +0000244 Assignment* assignment =
245 factory()->NewAssignment(Token::INIT, proxy, value, pos);
246 block_->statements()->Add(
247 factory()->NewExpressionStatement(assignment, pos), zone());
248 }
249}
250
251
252Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
253 auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
254 if (value != nullptr) {
255 auto assignment = factory()->NewAssignment(
256 Token::ASSIGN, factory()->NewVariableProxy(temp), value,
Ben Murdochf91f0612016-11-29 16:50:11 +0000257 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000258
259 block_->statements()->Add(
Ben Murdochf91f0612016-11-29 16:50:11 +0000260 factory()->NewExpressionStatement(assignment, kNoSourcePosition),
Ben Murdoch014dc512016-03-22 12:00:34 +0000261 zone());
262 }
263 return temp;
264}
265
266
Ben Murdoch109988c2016-05-18 11:27:45 +0100267void Parser::PatternRewriter::VisitRewritableExpression(
268 RewritableExpression* node) {
269 // If this is not a destructuring assignment...
270 if (!IsAssignmentContext() || !node->expression()->IsAssignment()) {
271 // Mark the node as rewritten to prevent redundant rewriting, and
Ben Murdoch014dc512016-03-22 12:00:34 +0000272 // perform BindingPattern rewriting
273 DCHECK(!node->is_rewritten());
274 node->Rewrite(node->expression());
Ben Murdochf91f0612016-11-29 16:50:11 +0000275 return Visit(node->expression());
Ben Murdoch014dc512016-03-22 12:00:34 +0000276 }
277
278 if (node->is_rewritten()) return;
279 DCHECK(IsAssignmentContext());
280 Assignment* assign = node->expression()->AsAssignment();
281 DCHECK_NOT_NULL(assign);
282 DCHECK_EQ(Token::ASSIGN, assign->op());
283
284 auto initializer = assign->value();
285 auto value = initializer;
286
287 if (IsInitializerContext()) {
288 // let {<pattern> = <init>} = <value>
289 // becomes
290 // temp = <value>;
291 // <pattern> = temp === undefined ? <init> : temp;
292 auto temp_var = CreateTempVar(current_value_);
293 Expression* is_undefined = factory()->NewCompareOperation(
294 Token::EQ_STRICT, factory()->NewVariableProxy(temp_var),
Ben Murdochf91f0612016-11-29 16:50:11 +0000295 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000296 value = factory()->NewConditional(is_undefined, initializer,
297 factory()->NewVariableProxy(temp_var),
Ben Murdochf91f0612016-11-29 16:50:11 +0000298 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000299 }
300
301 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
302 int pos = assign->position();
303 Block* old_block = block_;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100304 block_ = factory()->NewBlock(nullptr, 8, true, pos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000305 Variable* temp = nullptr;
306 Expression* pattern = assign->target();
307 Expression* old_value = current_value_;
308 current_value_ = value;
309 if (pattern->IsObjectLiteral()) {
310 VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
311 } else {
312 DCHECK(pattern->IsArrayLiteral());
313 VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
314 }
315 DCHECK_NOT_NULL(temp);
316 current_value_ = old_value;
317 Expression* expr = factory()->NewDoExpression(block_, temp, pos);
318 node->Rewrite(expr);
319 block_ = old_block;
320 if (block_) {
321 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
322 zone());
323 }
324 return set_context(old_context);
325}
326
Ben Murdochf91f0612016-11-29 16:50:11 +0000327// When an extra declaration scope needs to be inserted to account for
328// a sloppy eval in a default parameter or function body, the expressions
329// needs to be in that new inner scope which was added after initial
330// parsing.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100331void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) {
332 if (!IsBindingContext()) return;
333 if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return;
Ben Murdochf91f0612016-11-29 16:50:11 +0000334 if (!scope()->is_block_scope()) return;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100335
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100336 DCHECK(scope()->is_declaration_scope());
Ben Murdochf91f0612016-11-29 16:50:11 +0000337 DCHECK(scope()->outer_scope()->is_function_scope());
338 DCHECK(scope()->calls_sloppy_eval());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100339
Ben Murdochf91f0612016-11-29 16:50:11 +0000340 ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100341}
Ben Murdoch014dc512016-03-22 12:00:34 +0000342
343void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
344 Variable** temp_var) {
345 auto temp = *temp_var = CreateTempVar(current_value_);
346
347 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
348
349 for (ObjectLiteralProperty* property : *pattern->properties()) {
350 PatternContext context = SetInitializerContextIfNeeded(property->value());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100351
352 // Computed property names contain expressions which might require
353 // scope rewriting.
354 if (!property->key()->IsLiteral()) RewriteParameterScopes(property->key());
355
Ben Murdoch014dc512016-03-22 12:00:34 +0000356 RecurseIntoSubpattern(
357 property->value(),
358 factory()->NewProperty(factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000359 property->key(), kNoSourcePosition));
Ben Murdoch014dc512016-03-22 12:00:34 +0000360 set_context(context);
361 }
362}
363
364
365void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
366 Variable* temp_var = nullptr;
367 VisitObjectLiteral(node, &temp_var);
368}
369
370
371void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
372 Variable** temp_var) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100373 DCHECK(block_->ignore_completion_value());
374
Ben Murdoch014dc512016-03-22 12:00:34 +0000375 auto temp = *temp_var = CreateTempVar(current_value_);
Ben Murdoch014dc512016-03-22 12:00:34 +0000376 auto iterator = CreateTempVar(parser_->GetIterator(
Ben Murdochf91f0612016-11-29 16:50:11 +0000377 factory()->NewVariableProxy(temp), factory(), kNoSourcePosition));
378 auto done =
379 CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
Ben Murdoch014dc512016-03-22 12:00:34 +0000380 auto result = CreateTempVar();
381 auto v = CreateTempVar();
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100382 auto completion = CreateTempVar();
Ben Murdochf91f0612016-11-29 16:50:11 +0000383 auto nopos = kNoSourcePosition;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100384
385 // For the purpose of iterator finalization, we temporarily set block_ to a
386 // new block. In the main body of this function, we write to block_ (both
387 // explicitly and implicitly via recursion). At the end of the function, we
388 // wrap this new block in a try-finally statement, restore block_ to its
389 // original value, and add the try-finally statement to block_.
390 auto target = block_;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100391 block_ = factory()->NewBlock(nullptr, 8, true, nopos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000392
393 Spread* spread = nullptr;
394 for (Expression* value : *node->values()) {
395 if (value->IsSpread()) {
396 spread = value->AsSpread();
397 break;
398 }
399
400 PatternContext context = SetInitializerContextIfNeeded(value);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100401
Ben Murdoch014dc512016-03-22 12:00:34 +0000402 // if (!done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100403 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch014dc512016-03-22 12:00:34 +0000404 // result = IteratorNext(iterator);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100405 // if (result.done) {
406 // v = undefined;
407 // } else {
408 // v = result.value;
409 // done = false;
410 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000411 // }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100412 Statement* if_not_done;
413 {
414 auto result_done = factory()->NewProperty(
415 factory()->NewVariableProxy(result),
416 factory()->NewStringLiteral(ast_value_factory()->done_string(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000417 kNoSourcePosition),
418 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000419
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100420 auto assign_undefined = factory()->NewAssignment(
421 Token::ASSIGN, factory()->NewVariableProxy(v),
Ben Murdochf91f0612016-11-29 16:50:11 +0000422 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000423
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100424 auto assign_value = factory()->NewAssignment(
425 Token::ASSIGN, factory()->NewVariableProxy(v),
426 factory()->NewProperty(
427 factory()->NewVariableProxy(result),
428 factory()->NewStringLiteral(ast_value_factory()->value_string(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000429 kNoSourcePosition),
430 kNoSourcePosition),
431 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100432
433 auto unset_done = factory()->NewAssignment(
434 Token::ASSIGN, factory()->NewVariableProxy(done),
Ben Murdochf91f0612016-11-29 16:50:11 +0000435 factory()->NewBooleanLiteral(false, kNoSourcePosition),
436 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100437
438 auto inner_else =
Ben Murdochf91f0612016-11-29 16:50:11 +0000439 factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100440 inner_else->statements()->Add(
441 factory()->NewExpressionStatement(assign_value, nopos), zone());
442 inner_else->statements()->Add(
443 factory()->NewExpressionStatement(unset_done, nopos), zone());
444
445 auto inner_if = factory()->NewIfStatement(
446 result_done,
447 factory()->NewExpressionStatement(assign_undefined, nopos),
448 inner_else, nopos);
449
450 auto next_block =
Ben Murdochf91f0612016-11-29 16:50:11 +0000451 factory()->NewBlock(nullptr, 3, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100452 next_block->statements()->Add(
453 factory()->NewExpressionStatement(
454 factory()->NewAssignment(
455 Token::ASSIGN, factory()->NewVariableProxy(done),
456 factory()->NewBooleanLiteral(true, nopos), nopos),
457 nopos),
458 zone());
459 next_block->statements()->Add(
460 factory()->NewExpressionStatement(
461 parser_->BuildIteratorNextResult(
462 factory()->NewVariableProxy(iterator), result,
Ben Murdochf91f0612016-11-29 16:50:11 +0000463 kNoSourcePosition),
464 kNoSourcePosition),
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100465 zone());
466 next_block->statements()->Add(inner_if, zone());
467
468 if_not_done = factory()->NewIfStatement(
Ben Murdochf91f0612016-11-29 16:50:11 +0000469 factory()->NewUnaryOperation(
470 Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
471 next_block, factory()->NewEmptyStatement(kNoSourcePosition),
472 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100473 }
474 block_->statements()->Add(if_not_done, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000475
476 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100477 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100478 // completion = kAbruptCompletion;
479 Expression* proxy = factory()->NewVariableProxy(completion);
480 Expression* assignment = factory()->NewAssignment(
481 Token::ASSIGN, proxy,
482 factory()->NewSmiLiteral(kAbruptCompletion, nopos), nopos);
483 block_->statements()->Add(
484 factory()->NewExpressionStatement(assignment, nopos), zone());
485 }
486
Ben Murdoch014dc512016-03-22 12:00:34 +0000487 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100488
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100489 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100490 // completion = kNormalCompletion;
491 Expression* proxy = factory()->NewVariableProxy(completion);
492 Expression* assignment = factory()->NewAssignment(
493 Token::ASSIGN, proxy,
494 factory()->NewSmiLiteral(kNormalCompletion, nopos), nopos);
495 block_->statements()->Add(
496 factory()->NewExpressionStatement(assignment, nopos), zone());
497 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000498 }
499 set_context(context);
500 }
501
502 if (spread != nullptr) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100503 // A spread can only occur as the last component. It is not handled by
504 // RecurseIntoSubpattern above.
Ben Murdoch014dc512016-03-22 12:00:34 +0000505
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100506 // let array = [];
507 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100508 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100509 // result = IteratorNext(iterator);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100510 // if (!result.done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100511 // %AppendElement(array, result.value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100512 // done = false;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100513 // }
514 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000515
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100516 // let array = [];
517 Variable* array;
518 {
519 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
520 array = CreateTempVar(factory()->NewArrayLiteral(
521 empty_exprs,
522 // Reuse pattern's literal index - it is unused since there is no
523 // actual literal allocated.
Ben Murdochf91f0612016-11-29 16:50:11 +0000524 node->literal_index(), kNoSourcePosition));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100525 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000526
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100527 // done = true;
528 Statement* set_done = factory()->NewExpressionStatement(
529 factory()->NewAssignment(
530 Token::ASSIGN, factory()->NewVariableProxy(done),
531 factory()->NewBooleanLiteral(true, nopos), nopos),
532 nopos);
533
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100534 // result = IteratorNext(iterator);
535 Statement* get_next = factory()->NewExpressionStatement(
536 parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
537 result, nopos),
538 nopos);
539
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100540 // %AppendElement(array, result.value);
541 Statement* append_element;
542 {
543 auto args = new (zone()) ZoneList<Expression*>(2, zone());
544 args->Add(factory()->NewVariableProxy(array), zone());
545 args->Add(factory()->NewProperty(
546 factory()->NewVariableProxy(result),
547 factory()->NewStringLiteral(
548 ast_value_factory()->value_string(), nopos),
549 nopos),
550 zone());
551 append_element = factory()->NewExpressionStatement(
552 factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
553 nopos);
554 }
555
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100556 // done = false;
557 Statement* unset_done = factory()->NewExpressionStatement(
558 factory()->NewAssignment(
559 Token::ASSIGN, factory()->NewVariableProxy(done),
560 factory()->NewBooleanLiteral(false, nopos), nopos),
561 nopos);
562
563 // if (!result.done) { #append_element; #unset_done }
564 Statement* maybe_append_and_unset_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100565 {
566 Expression* result_done =
567 factory()->NewProperty(factory()->NewVariableProxy(result),
568 factory()->NewStringLiteral(
569 ast_value_factory()->done_string(), nopos),
570 nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100571
572 Block* then = factory()->NewBlock(nullptr, 2, true, nopos);
573 then->statements()->Add(append_element, zone());
574 then->statements()->Add(unset_done, zone());
575
576 maybe_append_and_unset_done = factory()->NewIfStatement(
577 factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
578 factory()->NewEmptyStatement(nopos), nopos);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100579 }
580
581 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100582 // #set_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100583 // #get_next;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100584 // #maybe_append_and_unset_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100585 // }
586 WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
587 {
588 Expression* condition = factory()->NewUnaryOperation(
589 Token::NOT, factory()->NewVariableProxy(done), nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100590 Block* body = factory()->NewBlock(nullptr, 3, true, nopos);
591 body->statements()->Add(set_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100592 body->statements()->Add(get_next, zone());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100593 body->statements()->Add(maybe_append_and_unset_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100594 loop->Initialize(condition, body);
595 }
596
597 block_->statements()->Add(loop, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000598 RecurseIntoSubpattern(spread->expression(),
599 factory()->NewVariableProxy(array));
600 }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100601
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100602 Expression* closing_condition = factory()->NewUnaryOperation(
603 Token::NOT, factory()->NewVariableProxy(done), nopos);
604 parser_->FinalizeIteratorUse(completion, closing_condition, iterator, block_,
605 target);
606 block_ = target;
Ben Murdoch014dc512016-03-22 12:00:34 +0000607}
608
609
610void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
611 Variable* temp_var = nullptr;
612 VisitArrayLiteral(node, &temp_var);
613}
614
615
616void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
617 // let {<pattern> = <init>} = <value>
618 // becomes
619 // temp = <value>;
620 // <pattern> = temp === undefined ? <init> : temp;
621 DCHECK_EQ(Token::ASSIGN, node->op());
622
623 auto initializer = node->value();
624 auto value = initializer;
625 auto temp = CreateTempVar(current_value_);
626
627 if (IsInitializerContext()) {
628 Expression* is_undefined = factory()->NewCompareOperation(
629 Token::EQ_STRICT, factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000630 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000631 value = factory()->NewConditional(is_undefined, initializer,
632 factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000633 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000634 }
635
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100636 // Initializer may have been parsed in the wrong scope.
637 RewriteParameterScopes(initializer);
Ben Murdoch014dc512016-03-22 12:00:34 +0000638
639 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
640 RecurseIntoSubpattern(node->target(), value);
641 set_context(old_context);
642}
643
644
645// =============== AssignmentPattern only ==================
646
647void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
648 DCHECK(IsAssignmentContext());
649 auto value = current_value_;
650
651 Assignment* assignment =
652 factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
653
654 block_->statements()->Add(
Ben Murdochf91f0612016-11-29 16:50:11 +0000655 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000656}
657
658
659// =============== UNREACHABLE =============================
660
Ben Murdoch014dc512016-03-22 12:00:34 +0000661#define NOT_A_PATTERN(Node) \
662 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
663 UNREACHABLE(); \
664 }
665
666NOT_A_PATTERN(BinaryOperation)
667NOT_A_PATTERN(Block)
668NOT_A_PATTERN(BreakStatement)
669NOT_A_PATTERN(Call)
670NOT_A_PATTERN(CallNew)
671NOT_A_PATTERN(CallRuntime)
672NOT_A_PATTERN(CaseClause)
673NOT_A_PATTERN(ClassLiteral)
674NOT_A_PATTERN(CompareOperation)
675NOT_A_PATTERN(Conditional)
676NOT_A_PATTERN(ContinueStatement)
677NOT_A_PATTERN(CountOperation)
678NOT_A_PATTERN(DebuggerStatement)
679NOT_A_PATTERN(DoExpression)
680NOT_A_PATTERN(DoWhileStatement)
681NOT_A_PATTERN(EmptyStatement)
682NOT_A_PATTERN(EmptyParentheses)
Ben Murdoch014dc512016-03-22 12:00:34 +0000683NOT_A_PATTERN(ExpressionStatement)
684NOT_A_PATTERN(ForInStatement)
685NOT_A_PATTERN(ForOfStatement)
686NOT_A_PATTERN(ForStatement)
687NOT_A_PATTERN(FunctionDeclaration)
688NOT_A_PATTERN(FunctionLiteral)
689NOT_A_PATTERN(IfStatement)
Ben Murdoch014dc512016-03-22 12:00:34 +0000690NOT_A_PATTERN(Literal)
691NOT_A_PATTERN(NativeFunctionLiteral)
692NOT_A_PATTERN(RegExpLiteral)
693NOT_A_PATTERN(ReturnStatement)
694NOT_A_PATTERN(SloppyBlockFunctionStatement)
695NOT_A_PATTERN(Spread)
696NOT_A_PATTERN(SuperPropertyReference)
697NOT_A_PATTERN(SuperCallReference)
698NOT_A_PATTERN(SwitchStatement)
699NOT_A_PATTERN(ThisFunction)
700NOT_A_PATTERN(Throw)
701NOT_A_PATTERN(TryCatchStatement)
702NOT_A_PATTERN(TryFinallyStatement)
703NOT_A_PATTERN(UnaryOperation)
704NOT_A_PATTERN(VariableDeclaration)
705NOT_A_PATTERN(WhileStatement)
706NOT_A_PATTERN(WithStatement)
707NOT_A_PATTERN(Yield)
708
709#undef NOT_A_PATTERN
710} // namespace internal
711} // namespace v8