Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: src/pattern-rewriter.cc

Issue 1411203002: [es6] implement destructuring assignment [clean diff] (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Completion-value reusing that may not necessarily accomplish anything Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parser.cc ('k') | test/mjsunit/harmony/destructuring-assignment.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/ast.h" 5 #include "src/ast.h"
6 #include "src/messages.h" 6 #include "src/messages.h"
7 #include "src/parser.h" 7 #include "src/parser.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 10
11 namespace internal { 11 namespace internal {
12 12
13 13
14 void Parser::PatternRewriter::DeclareAndInitializeVariables( 14 void Parser::PatternRewriter::DeclareAndInitializeVariables(
15 Block* block, const DeclarationDescriptor* declaration_descriptor, 15 Block* block, const DeclarationDescriptor* declaration_descriptor,
16 const DeclarationParsingResult::Declaration* declaration, 16 const DeclarationParsingResult::Declaration* declaration,
17 ZoneList<const AstRawString*>* names, bool* ok) { 17 ZoneList<const AstRawString*>* names, bool* ok) {
18 PatternRewriter rewriter; 18 PatternRewriter rewriter;
19 19
20 rewriter.parser_ = declaration_descriptor->parser;
21 rewriter.context_ = BINDING;
20 rewriter.pattern_ = declaration->pattern; 22 rewriter.pattern_ = declaration->pattern;
21 rewriter.initializer_position_ = declaration->initializer_position; 23 rewriter.initializer_position_ = declaration->initializer_position;
22 rewriter.block_ = block; 24 rewriter.block_ = block;
23 rewriter.descriptor_ = declaration_descriptor; 25 rewriter.descriptor_ = declaration_descriptor;
24 rewriter.names_ = names; 26 rewriter.names_ = names;
25 rewriter.ok_ = ok; 27 rewriter.ok_ = ok;
28 rewriter.rhs_ = nullptr;
26 29
27 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer); 30 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
28 } 31 }
29 32
30 33
34 Variable* Parser::PatternRewriter::RewriteDestructuringAssignment(
35 Parser* parser, Block* block, Expression* pattern, Expression* value,
36 Variable* result, bool* ok) {
37 PatternRewriter rewriter;
38
39 rewriter.parser_ = parser;
40 rewriter.context_ = ASSIGNMENT;
41 rewriter.pattern_ = pattern;
42 rewriter.block_ = block;
43 rewriter.descriptor_ = nullptr;
44 rewriter.names_ = nullptr;
45 rewriter.ok_ = ok;
46 rewriter.rhs_ = result;
47
48 rewriter.RecurseIntoSubpattern(rewriter.pattern_, value);
49 DCHECK_NOT_NULL(rewriter.rhs_);
50 return rewriter.rhs_;
51 }
52
53
31 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { 54 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
32 Expression* value = current_value_; 55 Expression* value = current_value_;
56
57 if (context() == ASSIGNMENT) {
58 // In an assignment context, simply perform the assignment
59 Assignment* assignment = factory()->NewAssignment(
60 Token::ASSIGN, pattern, value, pattern->position());
61 block_->statements()->Add(
62 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
63 zone());
64 return;
65 }
66
33 descriptor_->scope->RemoveUnresolved(pattern); 67 descriptor_->scope->RemoveUnresolved(pattern);
34 68
35 // Declare variable. 69 // Declare variable.
36 // Note that we *always* must treat the initial value via a separate init 70 // Note that we *always* must treat the initial value via a separate init
37 // assignment for variables and constants because the value must be assigned 71 // assignment for variables and constants because the value must be assigned
38 // when the variable is encountered in the source. But the variable/constant 72 // when the variable is encountered in the source. But the variable/constant
39 // is declared (and set to 'undefined') upon entering the function within 73 // is declared (and set to 'undefined') upon entering the function within
40 // which the variable or constant is declared. Only function variables have 74 // which the variable or constant is declared. Only function variables have
41 // an initial value in the declaration (because they are initialized upon 75 // an initial value in the declaration (because they are initialized upon
42 // entering the function). 76 // entering the function).
43 // 77 //
44 // If we have a legacy const declaration, in an inner scope, the proxy 78 // If we have a legacy const declaration, in an inner scope, the proxy
45 // is always bound to the declared variable (independent of possibly 79 // is always bound to the declared variable (independent of possibly
46 // surrounding 'with' statements). 80 // surrounding 'with' statements).
47 // For let/const declarations in harmony mode, we can also immediately 81 // For let/const declarations in harmony mode, we can also immediately
48 // pre-resolve the proxy because it resides in the same scope as the 82 // pre-resolve the proxy because it resides in the same scope as the
49 // declaration. 83 // declaration.
50 Parser* parser = descriptor_->parser; 84 Parser* parser = parser_;
51 const AstRawString* name = pattern->raw_name(); 85 const AstRawString* name = pattern->raw_name();
52 VariableProxy* proxy = parser->NewUnresolved(name, descriptor_->mode); 86 VariableProxy* proxy = parser->NewUnresolved(name, descriptor_->mode);
53 Declaration* declaration = factory()->NewVariableDeclaration( 87 Declaration* declaration = factory()->NewVariableDeclaration(
54 proxy, descriptor_->mode, descriptor_->scope, 88 proxy, descriptor_->mode, descriptor_->scope,
55 descriptor_->declaration_pos); 89 descriptor_->declaration_pos);
56 Variable* var = parser->Declare(declaration, descriptor_->declaration_kind, 90 Variable* var = parser->Declare(declaration, descriptor_->declaration_kind,
57 descriptor_->mode != VAR, ok_, 91 descriptor_->mode != VAR, ok_,
58 descriptor_->hoist_scope); 92 descriptor_->hoist_scope);
59 if (!*ok_) return; 93 if (!*ok_) return;
60 DCHECK_NOT_NULL(var); 94 DCHECK_NOT_NULL(var);
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 Assignment* assignment = factory()->NewAssignment( 240 Assignment* assignment = factory()->NewAssignment(
207 descriptor_->init_op, proxy, value, descriptor_->initialization_pos); 241 descriptor_->init_op, proxy, value, descriptor_->initialization_pos);
208 block_->statements()->Add( 242 block_->statements()->Add(
209 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), 243 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
210 zone()); 244 zone());
211 } 245 }
212 } 246 }
213 247
214 248
215 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { 249 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
216 auto temp = descriptor_->parser->scope_->NewTemporary( 250 if (value && value->IsDoExpression()) {
217 ast_value_factory()->empty_string()); 251 // Re-use completion values from |do-expressions|
252 block_->statements()->Add(
caitp (gmail) 2015/10/19 12:10:50 I was hoping this would help reduce the number of
253 factory()->NewExpressionStatement(value, RelocInfo::kNoPosition),
254 zone());
255 return value->AsDoExpression()->result()->var();
256 }
257 auto temp = parser_scope()->NewTemporary(ast_value_factory()->empty_string());
218 if (value != nullptr) { 258 if (value != nullptr) {
219 auto assignment = factory()->NewAssignment( 259 auto assignment = factory()->NewAssignment(
220 Token::ASSIGN, factory()->NewVariableProxy(temp), value, 260 Token::ASSIGN, factory()->NewVariableProxy(temp), value,
221 RelocInfo::kNoPosition); 261 RelocInfo::kNoPosition);
222 262
223 block_->statements()->Add( 263 block_->statements()->Add(
224 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), 264 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
225 zone()); 265 zone());
226 } 266 }
227 return temp; 267 return temp;
228 } 268 }
229 269
230 270
231 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { 271 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) {
232 auto temp = CreateTempVar(current_value_); 272 auto temp = CreateTempVar(current_value_);
273 if (rhs_ == nullptr) rhs_ = temp;
233 274
234 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), 275 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
235 zone());
236 276
237 for (ObjectLiteralProperty* property : *pattern->properties()) { 277 for (ObjectLiteralProperty* property : *pattern->properties()) {
238 RecurseIntoSubpattern( 278 RecurseIntoSubpattern(
239 property->value(), 279 property->value(),
240 factory()->NewProperty(factory()->NewVariableProxy(temp), 280 factory()->NewProperty(factory()->NewVariableProxy(temp),
241 property->key(), RelocInfo::kNoPosition)); 281 property->key(), RelocInfo::kNoPosition));
242 } 282 }
243 } 283 }
244 284
245 285
246 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { 286 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
247 auto temp = CreateTempVar(current_value_); 287 auto temp = CreateTempVar(current_value_);
288 if (rhs_ == nullptr) rhs_ = temp;
248 289
249 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), 290 Block* outer_block = block_;
250 zone());
251 291
252 auto iterator = CreateTempVar(descriptor_->parser->GetIterator( 292 if (context() == ASSIGNMENT) {
253 factory()->NewVariableProxy(temp), factory())); 293 block_ = factory()->NewBlock(nullptr, 4, false, node->position());
294 }
295
296 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
297
298 auto iterator = CreateTempVar(
299 parser_->GetIterator(factory()->NewVariableProxy(temp), factory()));
254 auto done = CreateTempVar( 300 auto done = CreateTempVar(
255 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); 301 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
256 auto result = CreateTempVar(); 302 auto result = CreateTempVar();
257 auto v = CreateTempVar(); 303 auto v = CreateTempVar();
258 304
259 Spread* spread = nullptr; 305 Spread* spread = nullptr;
260 for (Expression* value : *node->values()) { 306 for (Expression* value : *node->values()) {
261 if (value->IsSpread()) { 307 if (value->IsSpread()) {
262 spread = value->AsSpread(); 308 spread = value->AsSpread();
263 break; 309 break;
264 } 310 }
265 311
266 // if (!done) { 312 // if (!done) {
267 // result = IteratorNext(iterator); 313 // result = IteratorNext(iterator);
268 // v = (done = result.done) ? undefined : result.value; 314 // v = (done = result.done) ? undefined : result.value;
269 // } 315 // }
270 auto next_block = 316 auto next_block =
271 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); 317 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
272 next_block->statements()->Add( 318 next_block->statements()->Add(factory()->NewExpressionStatement(
273 factory()->NewExpressionStatement( 319 parser_->BuildIteratorNextResult(
274 descriptor_->parser->BuildIteratorNextResult( 320 factory()->NewVariableProxy(iterator),
275 factory()->NewVariableProxy(iterator), result, 321 result, RelocInfo::kNoPosition),
276 RelocInfo::kNoPosition), 322 RelocInfo::kNoPosition),
277 RelocInfo::kNoPosition), 323 zone());
278 zone());
279 324
280 auto assign_to_done = factory()->NewAssignment( 325 auto assign_to_done = factory()->NewAssignment(
281 Token::ASSIGN, factory()->NewVariableProxy(done), 326 Token::ASSIGN, factory()->NewVariableProxy(done),
282 factory()->NewProperty( 327 factory()->NewProperty(
283 factory()->NewVariableProxy(result), 328 factory()->NewVariableProxy(result),
284 factory()->NewStringLiteral(ast_value_factory()->done_string(), 329 factory()->NewStringLiteral(ast_value_factory()->done_string(),
285 RelocInfo::kNoPosition), 330 RelocInfo::kNoPosition),
286 RelocInfo::kNoPosition), 331 RelocInfo::kNoPosition),
287 RelocInfo::kNoPosition); 332 RelocInfo::kNoPosition);
288 auto next_value = factory()->NewConditional( 333 auto next_value = factory()->NewConditional(
(...skipping 26 matching lines...) Expand all
315 } 360 }
316 361
317 if (spread != nullptr) { 362 if (spread != nullptr) {
318 // array = []; 363 // array = [];
319 // if (!done) %concat_iterable_to_array(array, iterator); 364 // if (!done) %concat_iterable_to_array(array, iterator);
320 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); 365 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
321 auto array = CreateTempVar(factory()->NewArrayLiteral( 366 auto array = CreateTempVar(factory()->NewArrayLiteral(
322 empty_exprs, 367 empty_exprs,
323 // Reuse pattern's literal index - it is unused since there is no 368 // Reuse pattern's literal index - it is unused since there is no
324 // actual literal allocated. 369 // actual literal allocated.
325 node->literal_index(), is_strong(descriptor_->parser->language_mode()), 370 node->literal_index(), is_strong(parser_->language_mode()),
326 RelocInfo::kNoPosition)); 371 RelocInfo::kNoPosition));
327 372
328 auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); 373 auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
329 arguments->Add(factory()->NewVariableProxy(array), zone()); 374 arguments->Add(factory()->NewVariableProxy(array), zone());
330 arguments->Add(factory()->NewVariableProxy(iterator), zone()); 375 arguments->Add(factory()->NewVariableProxy(iterator), zone());
331 auto spread_into_array_call = 376 auto spread_into_array_call =
332 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, 377 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
333 arguments, RelocInfo::kNoPosition); 378 arguments, RelocInfo::kNoPosition);
334 379
335 auto if_statement = factory()->NewIfStatement( 380 auto if_statement = factory()->NewIfStatement(
336 factory()->NewUnaryOperation(Token::NOT, 381 factory()->NewUnaryOperation(Token::NOT,
337 factory()->NewVariableProxy(done), 382 factory()->NewVariableProxy(done),
338 RelocInfo::kNoPosition), 383 RelocInfo::kNoPosition),
339 factory()->NewExpressionStatement(spread_into_array_call, 384 factory()->NewExpressionStatement(spread_into_array_call,
340 RelocInfo::kNoPosition), 385 RelocInfo::kNoPosition),
341 factory()->NewEmptyStatement(RelocInfo::kNoPosition), 386 factory()->NewEmptyStatement(RelocInfo::kNoPosition),
342 RelocInfo::kNoPosition); 387 RelocInfo::kNoPosition);
343 block_->statements()->Add(if_statement, zone()); 388 block_->statements()->Add(if_statement, zone());
344 389
345 RecurseIntoSubpattern(spread->expression(), 390 RecurseIntoSubpattern(spread->expression(),
346 factory()->NewVariableProxy(array)); 391 factory()->NewVariableProxy(array));
347 } 392 }
393
394 if (outer_block != block_) {
395 DoExpression* work =
396 factory()->NewDoExpression(block_, temp, node->position());
397 block_ = outer_block;
398 block_->statements()->Add(
399 factory()->NewExpressionStatement(work, node->position()), zone());
400 }
348 } 401 }
349 402
350 403
351 void Parser::PatternRewriter::VisitAssignment(Assignment* node) { 404 void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
352 // let {<pattern> = <init>} = <value> 405 // let {<pattern> = <init>} = <value>
353 // becomes 406 // becomes
354 // temp = <value>; 407 // temp = <value>;
355 // <pattern> = temp === undefined ? <init> : temp; 408 // <pattern> = temp === undefined ? <init> : temp;
409 PatternContext old_context = context();
410 if (old_context == INITIALIZER) {
411 set_context(ASSIGNMENT);
412 } else if (old_context == BINDING) {
413 set_context(INITIALIZER);
414 }
356 DCHECK(node->op() == Token::ASSIGN); 415 DCHECK(node->op() == Token::ASSIGN);
357 auto temp = CreateTempVar(current_value_); 416 auto temp = CreateTempVar(current_value_);
358 Expression* is_undefined = factory()->NewCompareOperation( 417 Expression* is_undefined = factory()->NewCompareOperation(
359 Token::EQ_STRICT, factory()->NewVariableProxy(temp), 418 Token::EQ_STRICT, factory()->NewVariableProxy(temp),
360 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), 419 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
361 RelocInfo::kNoPosition); 420 RelocInfo::kNoPosition);
362 Expression* value = factory()->NewConditional( 421 Expression* value = factory()->NewConditional(
363 is_undefined, node->value(), factory()->NewVariableProxy(temp), 422 is_undefined, node->value(), factory()->NewVariableProxy(temp),
364 RelocInfo::kNoPosition); 423 RelocInfo::kNoPosition);
365 RecurseIntoSubpattern(node->target(), value); 424 RecurseIntoSubpattern(node->target(), value);
425 set_context(old_context);
366 } 426 }
367 427
368 428
429 // =============== ASSIGNMENT-ONLY =========================
430
431 void Parser::PatternRewriter::VisitProperty(v8::internal::Property* pattern) {
432 DCHECK(context() == ASSIGNMENT);
433 Expression* value = current_value_;
434 Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, pattern,
435 value, pattern->position());
436 block_->statements()->Add(
437 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
438 zone());
439 }
440
441
369 // =============== UNREACHABLE ============================= 442 // =============== UNREACHABLE =============================
370 443
371 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); } 444 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }
372 445
373 #define NOT_A_PATTERN(Node) \ 446 #define NOT_A_PATTERN(Node) \
374 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \ 447 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
375 UNREACHABLE(); \ 448 UNREACHABLE(); \
376 } 449 }
377 450
378 NOT_A_PATTERN(BinaryOperation) 451 NOT_A_PATTERN(BinaryOperation)
(...skipping 17 matching lines...) Expand all
396 NOT_A_PATTERN(ExpressionStatement) 469 NOT_A_PATTERN(ExpressionStatement)
397 NOT_A_PATTERN(ForInStatement) 470 NOT_A_PATTERN(ForInStatement)
398 NOT_A_PATTERN(ForOfStatement) 471 NOT_A_PATTERN(ForOfStatement)
399 NOT_A_PATTERN(ForStatement) 472 NOT_A_PATTERN(ForStatement)
400 NOT_A_PATTERN(FunctionDeclaration) 473 NOT_A_PATTERN(FunctionDeclaration)
401 NOT_A_PATTERN(FunctionLiteral) 474 NOT_A_PATTERN(FunctionLiteral)
402 NOT_A_PATTERN(IfStatement) 475 NOT_A_PATTERN(IfStatement)
403 NOT_A_PATTERN(ImportDeclaration) 476 NOT_A_PATTERN(ImportDeclaration)
404 NOT_A_PATTERN(Literal) 477 NOT_A_PATTERN(Literal)
405 NOT_A_PATTERN(NativeFunctionLiteral) 478 NOT_A_PATTERN(NativeFunctionLiteral)
406 NOT_A_PATTERN(Property)
407 NOT_A_PATTERN(RegExpLiteral) 479 NOT_A_PATTERN(RegExpLiteral)
408 NOT_A_PATTERN(ReturnStatement) 480 NOT_A_PATTERN(ReturnStatement)
409 NOT_A_PATTERN(SloppyBlockFunctionStatement) 481 NOT_A_PATTERN(SloppyBlockFunctionStatement)
410 NOT_A_PATTERN(Spread) 482 NOT_A_PATTERN(Spread)
411 NOT_A_PATTERN(SuperPropertyReference) 483 NOT_A_PATTERN(SuperPropertyReference)
412 NOT_A_PATTERN(SuperCallReference) 484 NOT_A_PATTERN(SuperCallReference)
413 NOT_A_PATTERN(SwitchStatement) 485 NOT_A_PATTERN(SwitchStatement)
414 NOT_A_PATTERN(ThisFunction) 486 NOT_A_PATTERN(ThisFunction)
415 NOT_A_PATTERN(Throw) 487 NOT_A_PATTERN(Throw)
416 NOT_A_PATTERN(TryCatchStatement) 488 NOT_A_PATTERN(TryCatchStatement)
417 NOT_A_PATTERN(TryFinallyStatement) 489 NOT_A_PATTERN(TryFinallyStatement)
418 NOT_A_PATTERN(UnaryOperation) 490 NOT_A_PATTERN(UnaryOperation)
419 NOT_A_PATTERN(VariableDeclaration) 491 NOT_A_PATTERN(VariableDeclaration)
420 NOT_A_PATTERN(WhileStatement) 492 NOT_A_PATTERN(WhileStatement)
421 NOT_A_PATTERN(WithStatement) 493 NOT_A_PATTERN(WithStatement)
422 NOT_A_PATTERN(Yield) 494 NOT_A_PATTERN(Yield)
423 495
424 #undef NOT_A_PATTERN 496 #undef NOT_A_PATTERN
425 } // namespace internal 497 } // namespace internal
426 } // namespace v8 498 } // namespace v8
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | test/mjsunit/harmony/destructuring-assignment.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698