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

Side by Side Diff: runtime/vm/parser.cc

Issue 9310007: Allow assignment expressions in conditional expressions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/language/src/CondExprTest.dart » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 5435 matching lines...) Expand 10 before | Expand all | Expand 10 after
5446 5446
5447 static bool IsLocalOrLiteralNode(AstNode* node) { 5447 static bool IsLocalOrLiteralNode(AstNode* node) {
5448 return node->IsLoadLocalNode() || node->IsLiteralNode(); 5448 return node->IsLoadLocalNode() || node->IsLiteralNode();
5449 } 5449 }
5450 5450
5451 5451
5452 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_index, 5452 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_index,
5453 intptr_t token_id, 5453 intptr_t token_id,
5454 const char* s) { 5454 const char* s) {
5455 char name[64]; 5455 char name[64];
5456 OS::SNPrint(name, 64, "%s%d", s, token_id); 5456 OS::SNPrint(name, 64, ":%s%d", s, token_id);
5457 LocalVariable* temp = 5457 LocalVariable* temp =
5458 new LocalVariable(token_index, 5458 new LocalVariable(token_index,
5459 String::ZoneHandle(String::NewSymbol(name)), 5459 String::ZoneHandle(String::NewSymbol(name)),
5460 Type::ZoneHandle(Type::DynamicType())); 5460 Type::ZoneHandle(Type::DynamicType()));
5461 temp->set_is_final(); 5461 temp->set_is_final();
5462 current_block_->scope->AddVariable(temp); 5462 current_block_->scope->AddVariable(temp);
5463 return temp; 5463 return temp;
5464 } 5464 }
5465 5465
5466 5466
5467 // If 'node' can create side effects, store its result in a temporary variable 5467 // If 'node' can create side effects, store its result in a temporary variable
5468 // and return a LoadLocalNode instead. 5468 // and return a LoadLocalNode instead.
5469 // Side effect free nodes are LoadLocalNode and LiteralNode. 5469 // Side effect free nodes are LoadLocalNode and LiteralNode.
5470 AstNode* Parser::AsSideEffectFreeNode(AstNode* node) { 5470 AstNode* Parser::AsSideEffectFreeNode(AstNode* node) {
5471 if (node->IsLoadIndexedNode()) { 5471 if (node->IsLoadIndexedNode()) {
5472 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); 5472 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode();
5473 intptr_t token_id = node->id(); 5473 intptr_t token_id = node->id();
5474 intptr_t token_index = node->token_index(); 5474 intptr_t token_index = node->token_index();
5475 node = NULL; // Do not use it. 5475 node = NULL; // Do not use it.
5476 // The array object access may not have side effects.
5477 // First, evaluate the array object expression if it might have side
5478 // effects.
5479 if (!IsLocalOrLiteralNode(load_indexed->array())) {
5480 LocalVariable* temp =
5481 CreateTempConstVariable(token_index, token_id, "lia");
5482 AstNode* save =
5483 new StoreLocalNode(token_index, *temp, load_indexed->array());
5484 current_block_->statements->Add(save);
5485 AstNode* load = new LoadLocalNode(token_index, *temp);
5486 load_indexed = new LoadIndexedNode(token_index,
5487 load,
5488 load_indexed->index_expr());
5489 }
5490 // Second, evaluate the index expression and store in a temporary
5491 // variable if it might have side effects.
5476 if (!IsLocalOrLiteralNode(load_indexed->index_expr())) { 5492 if (!IsLocalOrLiteralNode(load_indexed->index_expr())) {
5477 LocalVariable* temp = 5493 LocalVariable* temp =
5478 CreateTempConstVariable(token_index, token_id, "lix"); 5494 CreateTempConstVariable(token_index, token_id, "lix");
5479 AstNode* save = 5495 AstNode* save =
5480 new StoreLocalNode(token_index, *temp, load_indexed->index_expr()); 5496 new StoreLocalNode(token_index, *temp, load_indexed->index_expr());
5481 current_block_->statements->Add(save); 5497 current_block_->statements->Add(save);
5482 AstNode* load = new LoadLocalNode(token_index, *temp); 5498 AstNode* load = new LoadLocalNode(token_index, *temp);
5483 load_indexed = new LoadIndexedNode(token_index, 5499 load_indexed = new LoadIndexedNode(token_index,
5484 load_indexed->array(), 5500 load_indexed->array(),
5485 load); 5501 load);
5486 } 5502 }
5487 // The array object access may not have side effects.
5488 if (!IsLocalOrLiteralNode(load_indexed->array())) {
5489 LocalVariable* temp =
5490 CreateTempConstVariable(token_index, token_id, "lia");
5491 AstNode* save =
5492 new StoreLocalNode(token_index, *temp, load_indexed->array());
5493 current_block_->statements->Add(save);
5494 AstNode* load = new LoadLocalNode(token_index, *temp);
5495 load_indexed = new LoadIndexedNode(token_index,
5496 load,
5497 load_indexed->index_expr());
5498 }
5499 return load_indexed; 5503 return load_indexed;
5500 } 5504 }
5501 if (node->IsInstanceGetterNode()) { 5505 if (node->IsInstanceGetterNode()) {
5502 InstanceGetterNode* getter = node->AsInstanceGetterNode(); 5506 InstanceGetterNode* getter = node->AsInstanceGetterNode();
5503 intptr_t token_index = node->token_index(); 5507 intptr_t token_index = node->token_index();
5504 intptr_t token_id = node->id(); 5508 intptr_t token_id = node->id();
5505 node = NULL; // Do not use it. 5509 node = NULL; // Do not use it.
5506 if (!IsLocalOrLiteralNode(getter->receiver())) { 5510 if (!IsLocalOrLiteralNode(getter->receiver())) {
5507 LocalVariable* temp = 5511 LocalVariable* temp =
5508 CreateTempConstVariable(token_index, token_id, "igr"); 5512 CreateTempConstVariable(token_index, token_id, "igr");
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
5636 return expr->AsLiteralNode(); 5640 return expr->AsLiteralNode();
5637 } 5641 }
5638 5642
5639 5643
5640 AstNode* Parser::ParseConditionalExpr() { 5644 AstNode* Parser::ParseConditionalExpr() {
5641 TRACE_PARSER("ParseConditionalExpr"); 5645 TRACE_PARSER("ParseConditionalExpr");
5642 const intptr_t expr_pos = token_index_; 5646 const intptr_t expr_pos = token_index_;
5643 AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kOR)); 5647 AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kOR));
5644 if (CurrentToken() == Token::kCONDITIONAL) { 5648 if (CurrentToken() == Token::kCONDITIONAL) {
5645 ConsumeToken(); 5649 ConsumeToken();
5646 AstNode* expr1 = ParseConditionalExpr(); 5650 AstNode* expr1 = ParseExpr(kAllowConst);
5647 ExpectToken(Token::kCOLON); 5651 ExpectToken(Token::kCOLON);
5648 AstNode* expr2 = ParseConditionalExpr(); 5652 AstNode* expr2 = ParseExpr(kAllowConst);
5649 expr = new ConditionalExprNode(expr_pos, expr, expr1, expr2); 5653 expr = new ConditionalExprNode(expr_pos, expr, expr1, expr2);
5650 } 5654 }
5651 return expr; 5655 return expr;
5652 } 5656 }
5653 5657
5654 5658
5655 AstNode* Parser::ParseUnaryExpr() { 5659 AstNode* Parser::ParseUnaryExpr() {
5656 TRACE_PARSER("ParseUnaryExpr"); 5660 TRACE_PARSER("ParseUnaryExpr");
5657 AstNode* expr = NULL; 5661 AstNode* expr = NULL;
5658 const intptr_t op_pos = token_index_; 5662 const intptr_t op_pos = token_index_;
(...skipping 2025 matching lines...) Expand 10 before | Expand all | Expand 10 after
7684 ConsumeToken(); 7688 ConsumeToken();
7685 SkipUnaryExpr(); 7689 SkipUnaryExpr();
7686 } 7690 }
7687 } 7691 }
7688 7692
7689 7693
7690 void Parser::SkipConditionalExpr() { 7694 void Parser::SkipConditionalExpr() {
7691 SkipBinaryExpr(); 7695 SkipBinaryExpr();
7692 if (CurrentToken() == Token::kCONDITIONAL) { 7696 if (CurrentToken() == Token::kCONDITIONAL) {
7693 ConsumeToken(); 7697 ConsumeToken();
7694 SkipConditionalExpr(); 7698 SkipExpr();
7695 ExpectToken(Token::kCOLON); 7699 ExpectToken(Token::kCOLON);
7696 SkipConditionalExpr(); 7700 SkipExpr();
7697 } 7701 }
7698 } 7702 }
7699 7703
7700 7704
7701 void Parser::SkipExpr() { 7705 void Parser::SkipExpr() {
7702 SkipConditionalExpr(); 7706 SkipConditionalExpr();
7703 if (Token::IsAssignmentOperator(CurrentToken())) { 7707 if (Token::IsAssignmentOperator(CurrentToken())) {
7704 ConsumeToken(); 7708 ConsumeToken();
7705 SkipExpr(); 7709 SkipExpr();
7706 } 7710 }
(...skipping 10 matching lines...) Expand all
7717 void Parser::SkipQualIdent() { 7721 void Parser::SkipQualIdent() {
7718 ASSERT(IsIdentifier()); 7722 ASSERT(IsIdentifier());
7719 ConsumeToken(); 7723 ConsumeToken();
7720 if (CurrentToken() == Token::kPERIOD) { 7724 if (CurrentToken() == Token::kPERIOD) {
7721 ConsumeToken(); // Consume the kPERIOD token. 7725 ConsumeToken(); // Consume the kPERIOD token.
7722 ExpectIdentifier("identifier expected after '.'"); 7726 ExpectIdentifier("identifier expected after '.'");
7723 } 7727 }
7724 } 7728 }
7725 7729
7726 } // namespace dart 7730 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/language/src/CondExprTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698