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

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: 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
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 auto temp = parser_scope()->NewTemporary(ast_value_factory()->empty_string());
217 ast_value_factory()->empty_string());
218 if (value != nullptr) { 251 if (value != nullptr) {
219 auto assignment = factory()->NewAssignment( 252 auto assignment = factory()->NewAssignment(
220 Token::ASSIGN, factory()->NewVariableProxy(temp), value, 253 Token::ASSIGN, factory()->NewVariableProxy(temp), value,
221 RelocInfo::kNoPosition); 254 RelocInfo::kNoPosition);
222 255
223 block_->statements()->Add( 256 block_->statements()->Add(
224 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), 257 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
225 zone()); 258 zone());
226 } 259 }
227 return temp; 260 return temp;
228 } 261 }
229 262
230 263
231 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { 264 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) {
232 auto temp = CreateTempVar(current_value_); 265 auto temp = CreateTempVar(current_value_);
266 if (rhs_ == nullptr) rhs_ = temp;
233 267
234 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), 268 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
235 zone());
236 269
237 for (ObjectLiteralProperty* property : *pattern->properties()) { 270 for (ObjectLiteralProperty* property : *pattern->properties()) {
238 RecurseIntoSubpattern( 271 RecurseIntoSubpattern(
239 property->value(), 272 property->value(),
240 factory()->NewProperty(factory()->NewVariableProxy(temp), 273 factory()->NewProperty(factory()->NewVariableProxy(temp),
241 property->key(), RelocInfo::kNoPosition)); 274 property->key(), RelocInfo::kNoPosition));
242 } 275 }
243 } 276 }
244 277
245 278
246 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { 279 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
247 auto temp = CreateTempVar(current_value_); 280 auto temp = CreateTempVar(current_value_);
281 if (rhs_ == nullptr) rhs_ = temp;
248 282
249 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), 283 Block* outer_block = block_;
250 zone());
251 284
252 auto iterator = CreateTempVar(descriptor_->parser->GetIterator( 285 if (context() == ASSIGNMENT) {
253 factory()->NewVariableProxy(temp), factory())); 286 block_ = factory()->NewBlock(nullptr, 4, false, node->position());
287 }
288
289 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
290
291 auto iterator = CreateTempVar(
292 parser_->GetIterator(factory()->NewVariableProxy(temp), factory()));
254 auto done = CreateTempVar( 293 auto done = CreateTempVar(
255 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); 294 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
256 auto result = CreateTempVar(); 295 auto result = CreateTempVar();
257 auto v = CreateTempVar(); 296 auto v = CreateTempVar();
258 297
259 Spread* spread = nullptr; 298 Spread* spread = nullptr;
260 for (Expression* value : *node->values()) { 299 for (Expression* value : *node->values()) {
261 if (value->IsSpread()) { 300 if (value->IsSpread()) {
262 spread = value->AsSpread(); 301 spread = value->AsSpread();
263 break; 302 break;
264 } 303 }
265 304
266 // if (!done) { 305 // if (!done) {
267 // result = IteratorNext(iterator); 306 // result = IteratorNext(iterator);
268 // v = (done = result.done) ? undefined : result.value; 307 // v = (done = result.done) ? undefined : result.value;
269 // } 308 // }
270 auto next_block = 309 auto next_block =
271 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); 310 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
272 next_block->statements()->Add( 311 next_block->statements()->Add(factory()->NewExpressionStatement(
273 factory()->NewExpressionStatement( 312 parser_->BuildIteratorNextResult(
274 descriptor_->parser->BuildIteratorNextResult( 313 factory()->NewVariableProxy(iterator),
275 factory()->NewVariableProxy(iterator), result, 314 result, RelocInfo::kNoPosition),
276 RelocInfo::kNoPosition), 315 RelocInfo::kNoPosition),
277 RelocInfo::kNoPosition), 316 zone());
278 zone());
279 317
280 auto assign_to_done = factory()->NewAssignment( 318 auto assign_to_done = factory()->NewAssignment(
281 Token::ASSIGN, factory()->NewVariableProxy(done), 319 Token::ASSIGN, factory()->NewVariableProxy(done),
282 factory()->NewProperty( 320 factory()->NewProperty(
283 factory()->NewVariableProxy(result), 321 factory()->NewVariableProxy(result),
284 factory()->NewStringLiteral(ast_value_factory()->done_string(), 322 factory()->NewStringLiteral(ast_value_factory()->done_string(),
285 RelocInfo::kNoPosition), 323 RelocInfo::kNoPosition),
286 RelocInfo::kNoPosition), 324 RelocInfo::kNoPosition),
287 RelocInfo::kNoPosition); 325 RelocInfo::kNoPosition);
288 auto next_value = factory()->NewConditional( 326 auto next_value = factory()->NewConditional(
(...skipping 26 matching lines...) Expand all
315 } 353 }
316 354
317 if (spread != nullptr) { 355 if (spread != nullptr) {
318 // array = []; 356 // array = [];
319 // if (!done) %concat_iterable_to_array(array, iterator); 357 // if (!done) %concat_iterable_to_array(array, iterator);
320 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); 358 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
321 auto array = CreateTempVar(factory()->NewArrayLiteral( 359 auto array = CreateTempVar(factory()->NewArrayLiteral(
322 empty_exprs, 360 empty_exprs,
323 // Reuse pattern's literal index - it is unused since there is no 361 // Reuse pattern's literal index - it is unused since there is no
324 // actual literal allocated. 362 // actual literal allocated.
325 node->literal_index(), is_strong(descriptor_->parser->language_mode()), 363 node->literal_index(), is_strong(parser_->language_mode()),
326 RelocInfo::kNoPosition)); 364 RelocInfo::kNoPosition));
327 365
328 auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); 366 auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
329 arguments->Add(factory()->NewVariableProxy(array), zone()); 367 arguments->Add(factory()->NewVariableProxy(array), zone());
330 arguments->Add(factory()->NewVariableProxy(iterator), zone()); 368 arguments->Add(factory()->NewVariableProxy(iterator), zone());
331 auto spread_into_array_call = 369 auto spread_into_array_call =
332 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, 370 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
333 arguments, RelocInfo::kNoPosition); 371 arguments, RelocInfo::kNoPosition);
334 372
335 auto if_statement = factory()->NewIfStatement( 373 auto if_statement = factory()->NewIfStatement(
336 factory()->NewUnaryOperation(Token::NOT, 374 factory()->NewUnaryOperation(Token::NOT,
337 factory()->NewVariableProxy(done), 375 factory()->NewVariableProxy(done),
338 RelocInfo::kNoPosition), 376 RelocInfo::kNoPosition),
339 factory()->NewExpressionStatement(spread_into_array_call, 377 factory()->NewExpressionStatement(spread_into_array_call,
340 RelocInfo::kNoPosition), 378 RelocInfo::kNoPosition),
341 factory()->NewEmptyStatement(RelocInfo::kNoPosition), 379 factory()->NewEmptyStatement(RelocInfo::kNoPosition),
342 RelocInfo::kNoPosition); 380 RelocInfo::kNoPosition);
343 block_->statements()->Add(if_statement, zone()); 381 block_->statements()->Add(if_statement, zone());
344 382
345 RecurseIntoSubpattern(spread->expression(), 383 RecurseIntoSubpattern(spread->expression(),
346 factory()->NewVariableProxy(array)); 384 factory()->NewVariableProxy(array));
347 } 385 }
386
387 if (outer_block != block_) {
388 DoExpression* work =
389 factory()->NewDoExpression(block_, temp, node->position());
390 block_ = outer_block;
391 block_->statements()->Add(
392 factory()->NewExpressionStatement(work, node->position()), zone());
393 }
348 } 394 }
349 395
350 396
351 void Parser::PatternRewriter::VisitAssignment(Assignment* node) { 397 void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
352 // let {<pattern> = <init>} = <value> 398 // let {<pattern> = <init>} = <value>
353 // becomes 399 // becomes
354 // temp = <value>; 400 // temp = <value>;
355 // <pattern> = temp === undefined ? <init> : temp; 401 // <pattern> = temp === undefined ? <init> : temp;
402 PatternContext old_context = context();
403 if (old_context == INITIALIZER) {
404 set_context(ASSIGNMENT);
405 } else if (old_context == BINDING) {
406 set_context(INITIALIZER);
407 }
356 DCHECK(node->op() == Token::ASSIGN); 408 DCHECK(node->op() == Token::ASSIGN);
357 auto temp = CreateTempVar(current_value_); 409 auto temp = CreateTempVar(current_value_);
358 Expression* is_undefined = factory()->NewCompareOperation( 410 Expression* is_undefined = factory()->NewCompareOperation(
359 Token::EQ_STRICT, factory()->NewVariableProxy(temp), 411 Token::EQ_STRICT, factory()->NewVariableProxy(temp),
360 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), 412 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
361 RelocInfo::kNoPosition); 413 RelocInfo::kNoPosition);
362 Expression* value = factory()->NewConditional( 414 Expression* value = factory()->NewConditional(
363 is_undefined, node->value(), factory()->NewVariableProxy(temp), 415 is_undefined, node->value(), factory()->NewVariableProxy(temp),
364 RelocInfo::kNoPosition); 416 RelocInfo::kNoPosition);
365 RecurseIntoSubpattern(node->target(), value); 417 RecurseIntoSubpattern(node->target(), value);
418 set_context(old_context);
366 } 419 }
367 420
368 421
422 // =============== ASSIGNMENT-ONLY =========================
423
424 void Parser::PatternRewriter::VisitProperty(v8::internal::Property* pattern) {
425 DCHECK(context() == ASSIGNMENT);
426 Expression* value = current_value_;
427 Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, pattern,
428 value, pattern->position());
429 block_->statements()->Add(
430 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
431 zone());
432 }
433
434
369 // =============== UNREACHABLE ============================= 435 // =============== UNREACHABLE =============================
370 436
371 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); } 437 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }
372 438
373 #define NOT_A_PATTERN(Node) \ 439 #define NOT_A_PATTERN(Node) \
374 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \ 440 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
375 UNREACHABLE(); \ 441 UNREACHABLE(); \
376 } 442 }
377 443
378 NOT_A_PATTERN(BinaryOperation) 444 NOT_A_PATTERN(BinaryOperation)
(...skipping 17 matching lines...) Expand all
396 NOT_A_PATTERN(ExpressionStatement) 462 NOT_A_PATTERN(ExpressionStatement)
397 NOT_A_PATTERN(ForInStatement) 463 NOT_A_PATTERN(ForInStatement)
398 NOT_A_PATTERN(ForOfStatement) 464 NOT_A_PATTERN(ForOfStatement)
399 NOT_A_PATTERN(ForStatement) 465 NOT_A_PATTERN(ForStatement)
400 NOT_A_PATTERN(FunctionDeclaration) 466 NOT_A_PATTERN(FunctionDeclaration)
401 NOT_A_PATTERN(FunctionLiteral) 467 NOT_A_PATTERN(FunctionLiteral)
402 NOT_A_PATTERN(IfStatement) 468 NOT_A_PATTERN(IfStatement)
403 NOT_A_PATTERN(ImportDeclaration) 469 NOT_A_PATTERN(ImportDeclaration)
404 NOT_A_PATTERN(Literal) 470 NOT_A_PATTERN(Literal)
405 NOT_A_PATTERN(NativeFunctionLiteral) 471 NOT_A_PATTERN(NativeFunctionLiteral)
406 NOT_A_PATTERN(Property)
407 NOT_A_PATTERN(RegExpLiteral) 472 NOT_A_PATTERN(RegExpLiteral)
408 NOT_A_PATTERN(ReturnStatement) 473 NOT_A_PATTERN(ReturnStatement)
409 NOT_A_PATTERN(SloppyBlockFunctionStatement) 474 NOT_A_PATTERN(SloppyBlockFunctionStatement)
410 NOT_A_PATTERN(Spread) 475 NOT_A_PATTERN(Spread)
411 NOT_A_PATTERN(SuperPropertyReference) 476 NOT_A_PATTERN(SuperPropertyReference)
412 NOT_A_PATTERN(SuperCallReference) 477 NOT_A_PATTERN(SuperCallReference)
413 NOT_A_PATTERN(SwitchStatement) 478 NOT_A_PATTERN(SwitchStatement)
414 NOT_A_PATTERN(ThisFunction) 479 NOT_A_PATTERN(ThisFunction)
415 NOT_A_PATTERN(Throw) 480 NOT_A_PATTERN(Throw)
416 NOT_A_PATTERN(TryCatchStatement) 481 NOT_A_PATTERN(TryCatchStatement)
417 NOT_A_PATTERN(TryFinallyStatement) 482 NOT_A_PATTERN(TryFinallyStatement)
418 NOT_A_PATTERN(UnaryOperation) 483 NOT_A_PATTERN(UnaryOperation)
419 NOT_A_PATTERN(VariableDeclaration) 484 NOT_A_PATTERN(VariableDeclaration)
420 NOT_A_PATTERN(WhileStatement) 485 NOT_A_PATTERN(WhileStatement)
421 NOT_A_PATTERN(WithStatement) 486 NOT_A_PATTERN(WithStatement)
422 NOT_A_PATTERN(Yield) 487 NOT_A_PATTERN(Yield)
423 488
424 #undef NOT_A_PATTERN 489 #undef NOT_A_PATTERN
425 } // namespace internal 490 } // namespace internal
426 } // namespace v8 491 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698