blob: b4312a2a302e5418b24a64331fae7053ed0f088a [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"
Ben Murdoch62ed6312017-06-06 11:06:27 +01007#include "src/objects-inl.h"
Ben Murdoch014dc512016-03-22 12:00:34 +00008#include "src/parsing/parameter-initializer-rewriter.h"
9#include "src/parsing/parser.h"
10
11namespace v8 {
12
13namespace internal {
14
15void Parser::PatternRewriter::DeclareAndInitializeVariables(
Ben Murdochf3b273f2017-01-17 12:11:28 +000016 Parser* parser, Block* block,
17 const DeclarationDescriptor* declaration_descriptor,
Ben Murdoch014dc512016-03-22 12:00:34 +000018 const DeclarationParsingResult::Declaration* declaration,
19 ZoneList<const AstRawString*>* names, bool* ok) {
20 PatternRewriter rewriter;
21
Ben Murdoch3b9bc312016-06-02 14:46:10 +010022 DCHECK(block->ignore_completion_value());
23
Ben Murdoch014dc512016-03-22 12:00:34 +000024 rewriter.scope_ = declaration_descriptor->scope;
Ben Murdochf3b273f2017-01-17 12:11:28 +000025 rewriter.parser_ = parser;
Ben Murdoch014dc512016-03-22 12:00:34 +000026 rewriter.context_ = BINDING;
27 rewriter.pattern_ = declaration->pattern;
28 rewriter.initializer_position_ = declaration->initializer_position;
29 rewriter.block_ = block;
30 rewriter.descriptor_ = declaration_descriptor;
31 rewriter.names_ = names;
32 rewriter.ok_ = ok;
33 rewriter.recursion_level_ = 0;
34
35 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
36}
37
38
39void Parser::PatternRewriter::RewriteDestructuringAssignment(
Ben Murdoch109988c2016-05-18 11:27:45 +010040 Parser* parser, RewritableExpression* to_rewrite, Scope* scope) {
Ben Murdochf3b273f2017-01-17 12:11:28 +000041 DCHECK(!scope->HasBeenRemoved());
Ben Murdoch014dc512016-03-22 12:00:34 +000042 DCHECK(!to_rewrite->is_rewritten());
43
44 bool ok = true;
Ben Murdochf3b273f2017-01-17 12:11:28 +000045
46 PatternRewriter rewriter;
Ben Murdoch014dc512016-03-22 12:00:34 +000047 rewriter.scope_ = scope;
48 rewriter.parser_ = parser;
49 rewriter.context_ = ASSIGNMENT;
50 rewriter.pattern_ = to_rewrite;
51 rewriter.block_ = nullptr;
52 rewriter.descriptor_ = nullptr;
53 rewriter.names_ = nullptr;
54 rewriter.ok_ = &ok;
55 rewriter.recursion_level_ = 0;
56
57 rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr);
58 DCHECK(ok);
59}
60
61
62Expression* Parser::PatternRewriter::RewriteDestructuringAssignment(
63 Parser* parser, Assignment* assignment, Scope* scope) {
64 DCHECK_NOT_NULL(assignment);
65 DCHECK_EQ(Token::ASSIGN, assignment->op());
Ben Murdoch109988c2016-05-18 11:27:45 +010066 auto to_rewrite = parser->factory()->NewRewritableExpression(assignment);
Ben Murdoch014dc512016-03-22 12:00:34 +000067 RewriteDestructuringAssignment(parser, to_rewrite, scope);
68 return to_rewrite->expression();
69}
70
71
Ben Murdoch014dc512016-03-22 12:00:34 +000072Parser::PatternRewriter::PatternContext
73Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
74 PatternContext old_context = context();
Ben Murdoch109988c2016-05-18 11:27:45 +010075 // AssignmentExpressions may occur in the Initializer position of a
76 // SingleNameBinding. Such expressions should not prompt a change in the
77 // pattern's context.
78 if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN &&
79 !IsInitializerContext()) {
Ben Murdoch014dc512016-03-22 12:00:34 +000080 set_context(ASSIGNMENT);
81 }
82 return old_context;
83}
84
85
86Parser::PatternRewriter::PatternContext
87Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) {
88 // Set appropriate initializer context for BindingElement and
89 // AssignmentElement nodes
90 PatternContext old_context = context();
91 bool is_destructuring_assignment =
Ben Murdoch109988c2016-05-18 11:27:45 +010092 node->IsRewritableExpression() &&
93 !node->AsRewritableExpression()->is_rewritten();
Ben Murdoch014dc512016-03-22 12:00:34 +000094 bool is_assignment =
95 node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN;
96 if (is_destructuring_assignment || is_assignment) {
97 switch (old_context) {
98 case BINDING:
99 set_context(INITIALIZER);
100 break;
101 case ASSIGNMENT:
102 set_context(ASSIGNMENT_INITIALIZER);
103 break;
104 default:
105 break;
106 }
107 }
108 return old_context;
109}
110
111
112void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
113 Expression* value = current_value_;
114
115 if (IsAssignmentContext()) {
116 // In an assignment context, simply perform the assignment
117 Assignment* assignment = factory()->NewAssignment(
118 Token::ASSIGN, pattern, value, pattern->position());
119 block_->statements()->Add(
120 factory()->NewExpressionStatement(assignment, pattern->position()),
121 zone());
122 return;
123 }
124
125 descriptor_->scope->RemoveUnresolved(pattern);
126
127 // Declare variable.
128 // Note that we *always* must treat the initial value via a separate init
129 // assignment for variables and constants because the value must be assigned
130 // when the variable is encountered in the source. But the variable/constant
131 // is declared (and set to 'undefined') upon entering the function within
132 // which the variable or constant is declared. Only function variables have
133 // an initial value in the declaration (because they are initialized upon
134 // entering the function).
Ben Murdoch014dc512016-03-22 12:00:34 +0000135 const AstRawString* name = pattern->raw_name();
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000136 VariableProxy* proxy =
137 factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position());
Ben Murdoch014dc512016-03-22 12:00:34 +0000138 Declaration* declaration = factory()->NewVariableDeclaration(
Ben Murdochf91f0612016-11-29 16:50:11 +0000139 proxy, descriptor_->scope, descriptor_->declaration_pos);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100140
141 // When an extra declaration scope needs to be inserted to account for
142 // a sloppy eval in a default parameter or function body, the parameter
143 // needs to be declared in the function's scope, not in the varblock
144 // scope which will be used for the initializer expression.
145 Scope* outer_function_scope = nullptr;
146 if (DeclaresParameterContainingSloppyEval()) {
147 outer_function_scope = descriptor_->scope->outer_scope();
148 }
Ben Murdochf3b273f2017-01-17 12:11:28 +0000149 Variable* var = parser_->Declare(
150 declaration, descriptor_->declaration_kind, descriptor_->mode,
151 Variable::DefaultInitializationFlag(descriptor_->mode), ok_,
Ben Murdoch62ed6312017-06-06 11:06:27 +0100152 outer_function_scope);
Ben Murdoch014dc512016-03-22 12:00:34 +0000153 if (!*ok_) return;
154 DCHECK_NOT_NULL(var);
Ben Murdochf91f0612016-11-29 16:50:11 +0000155 DCHECK(proxy->is_resolved());
156 DCHECK(initializer_position_ != kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000157 var->set_initializer_position(initializer_position_);
158
Ben Murdoch62ed6312017-06-06 11:06:27 +0100159 Scope* declaration_scope =
160 outer_function_scope != nullptr
161 ? outer_function_scope
162 : (IsLexicalVariableMode(descriptor_->mode)
163 ? descriptor_->scope
164 : descriptor_->scope->GetDeclarationScope());
Ben Murdochf91f0612016-11-29 16:50:11 +0000165 if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000166 parser_->ReportMessage(MessageTemplate::kTooManyVariables);
167 *ok_ = false;
168 return;
169 }
170 if (names_) {
171 names_->Add(name, zone());
172 }
173
Ben Murdochf91f0612016-11-29 16:50:11 +0000174 // If there's no initializer, we're done.
175 if (value == nullptr) return;
176
Ben Murdoch62ed6312017-06-06 11:06:27 +0100177 Scope* var_init_scope = descriptor_->scope;
178 MarkLoopVariableAsAssigned(var_init_scope, proxy->var());
179
Ben Murdochf91f0612016-11-29 16:50:11 +0000180 // A declaration of the form:
Ben Murdoch014dc512016-03-22 12:00:34 +0000181 //
182 // var v = x;
183 //
184 // is syntactic sugar for:
185 //
186 // var v; v = x;
187 //
Ben Murdochf91f0612016-11-29 16:50:11 +0000188 // In particular, we need to re-lookup 'v' as it may be a different
189 // 'v' than the 'v' in the declaration (e.g., if we are inside a
190 // 'with' statement or 'catch' block). Global var declarations
191 // also need special treatment.
Ben Murdoch014dc512016-03-22 12:00:34 +0000192
Ben Murdochf91f0612016-11-29 16:50:11 +0000193 if (descriptor_->mode == VAR && var_init_scope->is_script_scope()) {
194 // Global variable declarations must be compiled in a specific
195 // way. When the script containing the global variable declaration
196 // is entered, the global variable must be declared, so that if it
197 // doesn't exist (on the global object itself, see ES5 errata) it
198 // gets created with an initial undefined value. This is handled
199 // by the declarations part of the function representing the
200 // top-level global code; see Runtime::DeclareGlobalVariable. If
201 // it already exists (in the object or in a prototype), it is
202 // *not* touched until the variable declaration statement is
203 // executed.
204 //
205 // Executing the variable declaration statement will always
206 // guarantee to give the global object an own property.
207 // This way, global variable declarations can shadow
208 // properties in the prototype chain, but only after the variable
209 // declaration statement has been executed. This is important in
210 // browsers where the global object (window) has lots of
211 // properties defined in prototype objects.
Ben Murdoch014dc512016-03-22 12:00:34 +0000212
Ben Murdoch014dc512016-03-22 12:00:34 +0000213 ZoneList<Expression*>* arguments =
214 new (zone()) ZoneList<Expression*>(3, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000215 arguments->Add(
216 factory()->NewStringLiteral(name, descriptor_->declaration_pos),
217 zone());
Ben Murdochf91f0612016-11-29 16:50:11 +0000218 arguments->Add(factory()->NewNumberLiteral(var_init_scope->language_mode(),
219 kNoSourcePosition),
220 zone());
221 arguments->Add(value, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000222
Ben Murdochf91f0612016-11-29 16:50:11 +0000223 CallRuntime* initialize = factory()->NewCallRuntime(
224 Runtime::kInitializeVarGlobal, arguments, value->position());
225 block_->statements()->Add(
226 factory()->NewExpressionStatement(initialize, initialize->position()),
227 zone());
228 } else {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100229 // For 'let' and 'const' declared variables the initialization always
230 // assigns to the declared variable.
Ben Murdochf91f0612016-11-29 16:50:11 +0000231 // But for var declarations we need to do a new lookup.
232 if (descriptor_->mode == VAR) {
233 proxy = var_init_scope->NewUnresolved(factory(), name);
234 } else {
235 DCHECK_NOT_NULL(proxy);
236 DCHECK_NOT_NULL(proxy->var());
237 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000238 // Add break location for destructured sub-pattern.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100239 int pos = IsSubPattern() ? pattern->position() : value->position();
Ben Murdoch014dc512016-03-22 12:00:34 +0000240 Assignment* assignment =
241 factory()->NewAssignment(Token::INIT, proxy, value, pos);
242 block_->statements()->Add(
243 factory()->NewExpressionStatement(assignment, pos), zone());
244 }
245}
246
247
248Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
249 auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
250 if (value != nullptr) {
251 auto assignment = factory()->NewAssignment(
252 Token::ASSIGN, factory()->NewVariableProxy(temp), value,
Ben Murdochf91f0612016-11-29 16:50:11 +0000253 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000254
255 block_->statements()->Add(
Ben Murdochf91f0612016-11-29 16:50:11 +0000256 factory()->NewExpressionStatement(assignment, kNoSourcePosition),
Ben Murdoch014dc512016-03-22 12:00:34 +0000257 zone());
258 }
259 return temp;
260}
261
262
Ben Murdoch109988c2016-05-18 11:27:45 +0100263void Parser::PatternRewriter::VisitRewritableExpression(
264 RewritableExpression* node) {
265 // If this is not a destructuring assignment...
Ben Murdochf3b273f2017-01-17 12:11:28 +0000266 if (!IsAssignmentContext()) {
Ben Murdoch109988c2016-05-18 11:27:45 +0100267 // Mark the node as rewritten to prevent redundant rewriting, and
Ben Murdoch014dc512016-03-22 12:00:34 +0000268 // perform BindingPattern rewriting
269 DCHECK(!node->is_rewritten());
270 node->Rewrite(node->expression());
Ben Murdochf91f0612016-11-29 16:50:11 +0000271 return Visit(node->expression());
Ben Murdochf3b273f2017-01-17 12:11:28 +0000272 } else if (!node->expression()->IsAssignment()) {
273 return Visit(node->expression());
Ben Murdoch014dc512016-03-22 12:00:34 +0000274 }
275
276 if (node->is_rewritten()) return;
277 DCHECK(IsAssignmentContext());
278 Assignment* assign = node->expression()->AsAssignment();
279 DCHECK_NOT_NULL(assign);
280 DCHECK_EQ(Token::ASSIGN, assign->op());
281
282 auto initializer = assign->value();
283 auto value = initializer;
284
285 if (IsInitializerContext()) {
286 // let {<pattern> = <init>} = <value>
287 // becomes
288 // temp = <value>;
289 // <pattern> = temp === undefined ? <init> : temp;
290 auto temp_var = CreateTempVar(current_value_);
291 Expression* is_undefined = factory()->NewCompareOperation(
292 Token::EQ_STRICT, factory()->NewVariableProxy(temp_var),
Ben Murdochf91f0612016-11-29 16:50:11 +0000293 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000294 value = factory()->NewConditional(is_undefined, initializer,
295 factory()->NewVariableProxy(temp_var),
Ben Murdochf91f0612016-11-29 16:50:11 +0000296 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000297 }
298
299 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
300 int pos = assign->position();
301 Block* old_block = block_;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100302 block_ = factory()->NewBlock(nullptr, 8, true, pos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000303 Variable* temp = nullptr;
304 Expression* pattern = assign->target();
305 Expression* old_value = current_value_;
306 current_value_ = value;
307 if (pattern->IsObjectLiteral()) {
308 VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
309 } else {
310 DCHECK(pattern->IsArrayLiteral());
311 VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
312 }
313 DCHECK_NOT_NULL(temp);
314 current_value_ = old_value;
315 Expression* expr = factory()->NewDoExpression(block_, temp, pos);
316 node->Rewrite(expr);
317 block_ = old_block;
318 if (block_) {
319 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
320 zone());
321 }
Ben Murdoch62ed6312017-06-06 11:06:27 +0100322 set_context(old_context);
323}
324
325bool Parser::PatternRewriter::DeclaresParameterContainingSloppyEval() const {
326 // Need to check for a binding context to make sure we have a descriptor.
327 if (IsBindingContext() &&
328 // Only relevant for parameters.
329 descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
330 // And only when scope is a block scope;
331 // without eval, it is a function scope.
332 scope()->is_block_scope()) {
333 DCHECK(scope()->calls_sloppy_eval());
334 DCHECK(scope()->is_declaration_scope());
335 DCHECK(scope()->outer_scope()->is_function_scope());
336 return true;
337 }
338
339 return false;
Ben Murdoch014dc512016-03-22 12:00:34 +0000340}
341
Ben Murdochf91f0612016-11-29 16:50:11 +0000342// When an extra declaration scope needs to be inserted to account for
343// a sloppy eval in a default parameter or function body, the expressions
344// needs to be in that new inner scope which was added after initial
345// parsing.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100346void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) {
Ben Murdoch62ed6312017-06-06 11:06:27 +0100347 if (DeclaresParameterContainingSloppyEval()) {
348 ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope());
349 }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100350}
Ben Murdoch014dc512016-03-22 12:00:34 +0000351
352void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
353 Variable** temp_var) {
354 auto temp = *temp_var = CreateTempVar(current_value_);
355
Ben Murdoch62ed6312017-06-06 11:06:27 +0100356 ZoneList<Expression*>* rest_runtime_callargs = nullptr;
357 if (pattern->has_rest_property()) {
358 // non_rest_properties_count = pattern->properties()->length - 1;
359 // args_length = 1 + non_rest_properties_count because we need to
360 // pass temp as well to the runtime function.
361 int args_length = pattern->properties()->length();
362 rest_runtime_callargs =
363 new (zone()) ZoneList<Expression*>(args_length, zone());
364 rest_runtime_callargs->Add(factory()->NewVariableProxy(temp), zone());
365 }
366
Ben Murdoch014dc512016-03-22 12:00:34 +0000367 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
368
369 for (ObjectLiteralProperty* property : *pattern->properties()) {
370 PatternContext context = SetInitializerContextIfNeeded(property->value());
Ben Murdoch62ed6312017-06-06 11:06:27 +0100371 Expression* value;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100372
Ben Murdoch62ed6312017-06-06 11:06:27 +0100373 if (property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
374 // var { y, [x++]: a, ...c } = temp
375 // becomes
376 // var y = temp.y;
377 // var temp1 = %ToName(x++);
378 // var a = temp[temp1];
379 // var c;
380 // c = %CopyDataPropertiesWithExcludedProperties(temp, "y", temp1);
381 value = factory()->NewCallRuntime(
382 Runtime::kCopyDataPropertiesWithExcludedProperties,
383 rest_runtime_callargs, kNoSourcePosition);
384 } else {
385 Expression* key = property->key();
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100386
Ben Murdoch62ed6312017-06-06 11:06:27 +0100387 if (!key->IsLiteral()) {
388 // Computed property names contain expressions which might require
389 // scope rewriting.
390 RewriteParameterScopes(key);
391 }
392
393 if (pattern->has_rest_property()) {
394 Expression* excluded_property = key;
395
396 if (property->is_computed_name()) {
397 DCHECK(!key->IsPropertyName() || !key->IsNumberLiteral());
398 auto args = new (zone()) ZoneList<Expression*>(1, zone());
399 args->Add(key, zone());
400 auto to_name_key = CreateTempVar(factory()->NewCallRuntime(
401 Runtime::kToName, args, kNoSourcePosition));
402 key = factory()->NewVariableProxy(to_name_key);
403 excluded_property = factory()->NewVariableProxy(to_name_key);
404 } else {
405 DCHECK(key->IsPropertyName() || key->IsNumberLiteral());
406 }
407
408 DCHECK(rest_runtime_callargs != nullptr);
409 rest_runtime_callargs->Add(excluded_property, zone());
410 }
411
412 value = factory()->NewProperty(factory()->NewVariableProxy(temp), key,
413 kNoSourcePosition);
414 }
415
416 RecurseIntoSubpattern(property->value(), value);
Ben Murdoch014dc512016-03-22 12:00:34 +0000417 set_context(context);
418 }
419}
420
421
422void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
423 Variable* temp_var = nullptr;
424 VisitObjectLiteral(node, &temp_var);
425}
426
427
428void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
429 Variable** temp_var) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100430 DCHECK(block_->ignore_completion_value());
431
Ben Murdoch014dc512016-03-22 12:00:34 +0000432 auto temp = *temp_var = CreateTempVar(current_value_);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100433 auto iterator = CreateTempVar(
434 factory()->NewGetIterator(factory()->NewVariableProxy(temp),
435 IteratorType::kNormal, kNoSourcePosition));
Ben Murdochf91f0612016-11-29 16:50:11 +0000436 auto done =
437 CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
Ben Murdoch014dc512016-03-22 12:00:34 +0000438 auto result = CreateTempVar();
439 auto v = CreateTempVar();
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100440 auto completion = CreateTempVar();
Ben Murdochf91f0612016-11-29 16:50:11 +0000441 auto nopos = kNoSourcePosition;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100442
443 // For the purpose of iterator finalization, we temporarily set block_ to a
444 // new block. In the main body of this function, we write to block_ (both
445 // explicitly and implicitly via recursion). At the end of the function, we
446 // wrap this new block in a try-finally statement, restore block_ to its
447 // original value, and add the try-finally statement to block_.
448 auto target = block_;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100449 block_ = factory()->NewBlock(nullptr, 8, true, nopos);
Ben Murdoch014dc512016-03-22 12:00:34 +0000450
451 Spread* spread = nullptr;
452 for (Expression* value : *node->values()) {
453 if (value->IsSpread()) {
454 spread = value->AsSpread();
455 break;
456 }
457
458 PatternContext context = SetInitializerContextIfNeeded(value);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100459
Ben Murdoch014dc512016-03-22 12:00:34 +0000460 // if (!done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100461 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch014dc512016-03-22 12:00:34 +0000462 // result = IteratorNext(iterator);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100463 // if (result.done) {
464 // v = undefined;
465 // } else {
466 // v = result.value;
467 // done = false;
468 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000469 // }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100470 Statement* if_not_done;
471 {
472 auto result_done = factory()->NewProperty(
473 factory()->NewVariableProxy(result),
474 factory()->NewStringLiteral(ast_value_factory()->done_string(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000475 kNoSourcePosition),
476 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000477
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100478 auto assign_undefined = factory()->NewAssignment(
479 Token::ASSIGN, factory()->NewVariableProxy(v),
Ben Murdochf91f0612016-11-29 16:50:11 +0000480 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000481
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100482 auto assign_value = factory()->NewAssignment(
483 Token::ASSIGN, factory()->NewVariableProxy(v),
484 factory()->NewProperty(
485 factory()->NewVariableProxy(result),
486 factory()->NewStringLiteral(ast_value_factory()->value_string(),
Ben Murdochf91f0612016-11-29 16:50:11 +0000487 kNoSourcePosition),
488 kNoSourcePosition),
489 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100490
491 auto unset_done = factory()->NewAssignment(
492 Token::ASSIGN, factory()->NewVariableProxy(done),
Ben Murdochf91f0612016-11-29 16:50:11 +0000493 factory()->NewBooleanLiteral(false, kNoSourcePosition),
494 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100495
496 auto inner_else =
Ben Murdochf91f0612016-11-29 16:50:11 +0000497 factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100498 inner_else->statements()->Add(
499 factory()->NewExpressionStatement(assign_value, nopos), zone());
500 inner_else->statements()->Add(
501 factory()->NewExpressionStatement(unset_done, nopos), zone());
502
503 auto inner_if = factory()->NewIfStatement(
504 result_done,
505 factory()->NewExpressionStatement(assign_undefined, nopos),
506 inner_else, nopos);
507
508 auto next_block =
Ben Murdochf91f0612016-11-29 16:50:11 +0000509 factory()->NewBlock(nullptr, 3, true, kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100510 next_block->statements()->Add(
511 factory()->NewExpressionStatement(
512 factory()->NewAssignment(
513 Token::ASSIGN, factory()->NewVariableProxy(done),
514 factory()->NewBooleanLiteral(true, nopos), nopos),
515 nopos),
516 zone());
517 next_block->statements()->Add(
518 factory()->NewExpressionStatement(
519 parser_->BuildIteratorNextResult(
520 factory()->NewVariableProxy(iterator), result,
Ben Murdoch62ed6312017-06-06 11:06:27 +0100521 IteratorType::kNormal, kNoSourcePosition),
Ben Murdochf91f0612016-11-29 16:50:11 +0000522 kNoSourcePosition),
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100523 zone());
524 next_block->statements()->Add(inner_if, zone());
525
526 if_not_done = factory()->NewIfStatement(
Ben Murdochf91f0612016-11-29 16:50:11 +0000527 factory()->NewUnaryOperation(
528 Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
529 next_block, factory()->NewEmptyStatement(kNoSourcePosition),
530 kNoSourcePosition);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100531 }
532 block_->statements()->Add(if_not_done, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000533
534 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100535 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100536 // completion = kAbruptCompletion;
537 Expression* proxy = factory()->NewVariableProxy(completion);
538 Expression* assignment = factory()->NewAssignment(
539 Token::ASSIGN, proxy,
540 factory()->NewSmiLiteral(kAbruptCompletion, nopos), nopos);
541 block_->statements()->Add(
542 factory()->NewExpressionStatement(assignment, nopos), zone());
543 }
544
Ben Murdoch014dc512016-03-22 12:00:34 +0000545 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100546
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100547 {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100548 // completion = kNormalCompletion;
549 Expression* proxy = factory()->NewVariableProxy(completion);
550 Expression* assignment = factory()->NewAssignment(
551 Token::ASSIGN, proxy,
552 factory()->NewSmiLiteral(kNormalCompletion, nopos), nopos);
553 block_->statements()->Add(
554 factory()->NewExpressionStatement(assignment, nopos), zone());
555 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000556 }
557 set_context(context);
558 }
559
560 if (spread != nullptr) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100561 // A spread can only occur as the last component. It is not handled by
562 // RecurseIntoSubpattern above.
Ben Murdoch014dc512016-03-22 12:00:34 +0000563
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100564 // let array = [];
565 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100566 // done = true; // If .next, .done or .value throws, don't close.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100567 // result = IteratorNext(iterator);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100568 // if (!result.done) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100569 // %AppendElement(array, result.value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100570 // done = false;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100571 // }
572 // }
Ben Murdoch014dc512016-03-22 12:00:34 +0000573
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100574 // let array = [];
575 Variable* array;
576 {
577 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
Ben Murdoch62ed6312017-06-06 11:06:27 +0100578 array = CreateTempVar(
579 factory()->NewArrayLiteral(empty_exprs, kNoSourcePosition));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100580 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000581
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100582 // done = true;
583 Statement* set_done = factory()->NewExpressionStatement(
584 factory()->NewAssignment(
585 Token::ASSIGN, factory()->NewVariableProxy(done),
586 factory()->NewBooleanLiteral(true, nopos), nopos),
587 nopos);
588
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100589 // result = IteratorNext(iterator);
590 Statement* get_next = factory()->NewExpressionStatement(
591 parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
Ben Murdoch62ed6312017-06-06 11:06:27 +0100592 result, IteratorType::kNormal, nopos),
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100593 nopos);
594
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100595 // %AppendElement(array, result.value);
596 Statement* append_element;
597 {
598 auto args = new (zone()) ZoneList<Expression*>(2, zone());
599 args->Add(factory()->NewVariableProxy(array), zone());
600 args->Add(factory()->NewProperty(
601 factory()->NewVariableProxy(result),
602 factory()->NewStringLiteral(
603 ast_value_factory()->value_string(), nopos),
604 nopos),
605 zone());
606 append_element = factory()->NewExpressionStatement(
607 factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
608 nopos);
609 }
610
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100611 // done = false;
612 Statement* unset_done = factory()->NewExpressionStatement(
613 factory()->NewAssignment(
614 Token::ASSIGN, factory()->NewVariableProxy(done),
615 factory()->NewBooleanLiteral(false, nopos), nopos),
616 nopos);
617
618 // if (!result.done) { #append_element; #unset_done }
619 Statement* maybe_append_and_unset_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100620 {
621 Expression* result_done =
622 factory()->NewProperty(factory()->NewVariableProxy(result),
623 factory()->NewStringLiteral(
624 ast_value_factory()->done_string(), nopos),
625 nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100626
627 Block* then = factory()->NewBlock(nullptr, 2, true, nopos);
628 then->statements()->Add(append_element, zone());
629 then->statements()->Add(unset_done, zone());
630
631 maybe_append_and_unset_done = factory()->NewIfStatement(
632 factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
633 factory()->NewEmptyStatement(nopos), nopos);
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100634 }
635
636 // while (!done) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100637 // #set_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100638 // #get_next;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100639 // #maybe_append_and_unset_done;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100640 // }
641 WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
642 {
643 Expression* condition = factory()->NewUnaryOperation(
644 Token::NOT, factory()->NewVariableProxy(done), nopos);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100645 Block* body = factory()->NewBlock(nullptr, 3, true, nopos);
646 body->statements()->Add(set_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100647 body->statements()->Add(get_next, zone());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100648 body->statements()->Add(maybe_append_and_unset_done, zone());
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100649 loop->Initialize(condition, body);
650 }
651
652 block_->statements()->Add(loop, zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000653 RecurseIntoSubpattern(spread->expression(),
654 factory()->NewVariableProxy(array));
655 }
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100656
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100657 Expression* closing_condition = factory()->NewUnaryOperation(
658 Token::NOT, factory()->NewVariableProxy(done), nopos);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000659
660 parser_->FinalizeIteratorUse(scope(), completion, closing_condition, iterator,
Ben Murdoch62ed6312017-06-06 11:06:27 +0100661 block_, target, IteratorType::kNormal);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100662 block_ = target;
Ben Murdoch014dc512016-03-22 12:00:34 +0000663}
664
665
666void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
667 Variable* temp_var = nullptr;
668 VisitArrayLiteral(node, &temp_var);
669}
670
671
672void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
673 // let {<pattern> = <init>} = <value>
674 // becomes
675 // temp = <value>;
676 // <pattern> = temp === undefined ? <init> : temp;
677 DCHECK_EQ(Token::ASSIGN, node->op());
678
679 auto initializer = node->value();
680 auto value = initializer;
681 auto temp = CreateTempVar(current_value_);
682
683 if (IsInitializerContext()) {
684 Expression* is_undefined = factory()->NewCompareOperation(
685 Token::EQ_STRICT, factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000686 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000687 value = factory()->NewConditional(is_undefined, initializer,
688 factory()->NewVariableProxy(temp),
Ben Murdochf91f0612016-11-29 16:50:11 +0000689 kNoSourcePosition);
Ben Murdoch014dc512016-03-22 12:00:34 +0000690 }
691
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100692 // Initializer may have been parsed in the wrong scope.
693 RewriteParameterScopes(initializer);
Ben Murdoch014dc512016-03-22 12:00:34 +0000694
695 PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
696 RecurseIntoSubpattern(node->target(), value);
697 set_context(old_context);
698}
699
700
701// =============== AssignmentPattern only ==================
702
703void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
704 DCHECK(IsAssignmentContext());
705 auto value = current_value_;
706
707 Assignment* assignment =
708 factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
709
710 block_->statements()->Add(
Ben Murdochf91f0612016-11-29 16:50:11 +0000711 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
Ben Murdoch014dc512016-03-22 12:00:34 +0000712}
713
714
715// =============== UNREACHABLE =============================
716
Ben Murdoch014dc512016-03-22 12:00:34 +0000717#define NOT_A_PATTERN(Node) \
718 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
719 UNREACHABLE(); \
720 }
721
722NOT_A_PATTERN(BinaryOperation)
723NOT_A_PATTERN(Block)
724NOT_A_PATTERN(BreakStatement)
725NOT_A_PATTERN(Call)
726NOT_A_PATTERN(CallNew)
727NOT_A_PATTERN(CallRuntime)
728NOT_A_PATTERN(CaseClause)
729NOT_A_PATTERN(ClassLiteral)
730NOT_A_PATTERN(CompareOperation)
731NOT_A_PATTERN(Conditional)
732NOT_A_PATTERN(ContinueStatement)
733NOT_A_PATTERN(CountOperation)
734NOT_A_PATTERN(DebuggerStatement)
735NOT_A_PATTERN(DoExpression)
736NOT_A_PATTERN(DoWhileStatement)
737NOT_A_PATTERN(EmptyStatement)
738NOT_A_PATTERN(EmptyParentheses)
Ben Murdoch014dc512016-03-22 12:00:34 +0000739NOT_A_PATTERN(ExpressionStatement)
740NOT_A_PATTERN(ForInStatement)
741NOT_A_PATTERN(ForOfStatement)
742NOT_A_PATTERN(ForStatement)
743NOT_A_PATTERN(FunctionDeclaration)
744NOT_A_PATTERN(FunctionLiteral)
Ben Murdoch62ed6312017-06-06 11:06:27 +0100745NOT_A_PATTERN(GetIterator)
Ben Murdoch014dc512016-03-22 12:00:34 +0000746NOT_A_PATTERN(IfStatement)
Ben Murdoch014dc512016-03-22 12:00:34 +0000747NOT_A_PATTERN(Literal)
748NOT_A_PATTERN(NativeFunctionLiteral)
749NOT_A_PATTERN(RegExpLiteral)
750NOT_A_PATTERN(ReturnStatement)
751NOT_A_PATTERN(SloppyBlockFunctionStatement)
752NOT_A_PATTERN(Spread)
753NOT_A_PATTERN(SuperPropertyReference)
754NOT_A_PATTERN(SuperCallReference)
755NOT_A_PATTERN(SwitchStatement)
756NOT_A_PATTERN(ThisFunction)
757NOT_A_PATTERN(Throw)
758NOT_A_PATTERN(TryCatchStatement)
759NOT_A_PATTERN(TryFinallyStatement)
760NOT_A_PATTERN(UnaryOperation)
761NOT_A_PATTERN(VariableDeclaration)
762NOT_A_PATTERN(WhileStatement)
763NOT_A_PATTERN(WithStatement)
764NOT_A_PATTERN(Yield)
765
766#undef NOT_A_PATTERN
767} // namespace internal
768} // namespace v8