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

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

Issue 12381089: Fix for loop variable capturing (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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/block_scope_test.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 "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 5913 matching lines...) Expand 10 before | Expand all | Expand 10 after
5924 5924
5925 AstNode* Parser::ParseForStatement(String* label_name) { 5925 AstNode* Parser::ParseForStatement(String* label_name) {
5926 TRACE_PARSER("ParseForStatement"); 5926 TRACE_PARSER("ParseForStatement");
5927 const intptr_t for_pos = TokenPos(); 5927 const intptr_t for_pos = TokenPos();
5928 ConsumeToken(); 5928 ConsumeToken();
5929 ExpectToken(Token::kLPAREN); 5929 ExpectToken(Token::kLPAREN);
5930 SourceLabel* label = SourceLabel::New(for_pos, label_name, SourceLabel::kFor); 5930 SourceLabel* label = SourceLabel::New(for_pos, label_name, SourceLabel::kFor);
5931 if (IsForInStatement()) { 5931 if (IsForInStatement()) {
5932 return ParseForInStatement(for_pos, label); 5932 return ParseForInStatement(for_pos, label);
5933 } 5933 }
5934 OpenBlock(); 5934 // Open a block that contains the loop variable. Make it a loop block so
5935 // The label is added to the implicit scope that also contains 5935 // that we allocate a new context if the loop variable is captured.
5936 // the loop variable declarations. 5936 OpenLoopBlock();
5937 current_block_->scope->AddLabel(label);
5938 AstNode* initializer = NULL; 5937 AstNode* initializer = NULL;
5939 const intptr_t init_pos = TokenPos(); 5938 const intptr_t init_pos = TokenPos();
5940 LocalScope* init_scope = current_block_->scope; 5939 LocalScope* init_scope = current_block_->scope;
5941 if (CurrentToken() != Token::kSEMICOLON) { 5940 if (CurrentToken() != Token::kSEMICOLON) {
5942 if (IsVariableDeclaration()) { 5941 if (IsVariableDeclaration()) {
5943 initializer = ParseVariableDeclarationList(); 5942 initializer = ParseVariableDeclarationList();
5944 } else { 5943 } else {
5945 initializer = ParseExpr(kAllowConst, kConsumeCascades); 5944 initializer = ParseExpr(kAllowConst, kConsumeCascades);
5946 } 5945 }
5947 } 5946 }
5948 ExpectSemicolon(); 5947 ExpectSemicolon();
5949 AstNode* condition = NULL; 5948 AstNode* condition = NULL;
5950 if (CurrentToken() != Token::kSEMICOLON) { 5949 if (CurrentToken() != Token::kSEMICOLON) {
5951 condition = ParseExpr(kAllowConst, kConsumeCascades); 5950 condition = ParseExpr(kAllowConst, kConsumeCascades);
5952 } 5951 }
5953 ExpectSemicolon(); 5952 ExpectSemicolon();
5954 AstNode* increment = NULL; 5953 AstNode* increment = NULL;
5955 const intptr_t incr_pos = TokenPos(); 5954 const intptr_t incr_pos = TokenPos();
5956 LocalScope* incr_scope = current_block_->scope;
5957 if (CurrentToken() != Token::kRPAREN) { 5955 if (CurrentToken() != Token::kRPAREN) {
5958 increment = ParseExprList(); 5956 increment = ParseExprList();
5959 } 5957 }
5960 ExpectToken(Token::kRPAREN); 5958 ExpectToken(Token::kRPAREN);
5961 const bool parsing_loop_body = true; 5959 const bool parsing_loop_body = true;
5962 SequenceNode* body = ParseNestedStatement(parsing_loop_body, NULL); 5960 SequenceNode* body = ParseNestedStatement(parsing_loop_body, label);
5963 5961
5964 // Check whether any of the variables in the initializer part of 5962 // Check whether any of the variables in the initializer part of
5965 // the for statement are captured by a closure. If so, we insert a 5963 // the for statement are captured by a closure. If so, we insert a
5966 // node that creates a new Context for the loop variable before 5964 // node that creates a new Context for the loop variable before
5967 // the increment expression is evaluated. 5965 // the increment expression is evaluated.
5968 for (int i = 0; i < init_scope->num_variables(); i++) { 5966 for (int i = 0; i < init_scope->num_variables(); i++) {
5969 if (init_scope->VariableAt(i)->is_captured() && 5967 if (init_scope->VariableAt(i)->is_captured() &&
5970 (init_scope->VariableAt(i)->owner() == init_scope)) { 5968 (init_scope->VariableAt(i)->owner() == init_scope)) {
5971 SequenceNode* incr_sequence = new SequenceNode(incr_pos, incr_scope); 5969 SequenceNode* incr_sequence = new SequenceNode(incr_pos, NULL);
5972 incr_sequence->Add(new CloneContextNode(for_pos)); 5970 incr_sequence->Add(new CloneContextNode(for_pos));
5973 if (increment != NULL) { 5971 if (increment != NULL) {
5974 incr_sequence->Add(increment); 5972 incr_sequence->Add(increment);
5975 } 5973 }
5976 increment = incr_sequence; 5974 increment = incr_sequence;
5977 break; 5975 break;
5978 } 5976 }
5979 } 5977 }
5980 CloseBlock(); 5978 AstNode* for_node =
5981 return new ForNode(for_pos, 5979 new ForNode(for_pos,
5982 label, 5980 label,
5983 NodeAsSequenceNode(init_pos, initializer, init_scope), 5981 NodeAsSequenceNode(init_pos, initializer, NULL),
5984 condition, 5982 condition,
5985 NodeAsSequenceNode(incr_pos, increment, incr_scope), 5983 NodeAsSequenceNode(incr_pos, increment, NULL),
5986 body); 5984 body);
5985 current_block_->statements->Add(for_node);
5986 return CloseBlock();
5987 } 5987 }
5988 5988
5989 5989
5990 // Calling VM-internal helpers, uses implementation core library. 5990 // Calling VM-internal helpers, uses implementation core library.
5991 AstNode* Parser::MakeStaticCall(const String& cls_name, 5991 AstNode* Parser::MakeStaticCall(const String& cls_name,
5992 const String& func_name, 5992 const String& func_name,
5993 ArgumentListNode* arguments) { 5993 ArgumentListNode* arguments) {
5994 const Class& cls = Class::Handle(LookupCoreClass(cls_name)); 5994 const Class& cls = Class::Handle(LookupCoreClass(cls_name));
5995 ASSERT(!cls.IsNull()); 5995 ASSERT(!cls.IsNull());
5996 const Function& func = Function::ZoneHandle( 5996 const Function& func = Function::ZoneHandle(
(...skipping 4067 matching lines...) Expand 10 before | Expand all | Expand 10 after
10064 void Parser::SkipQualIdent() { 10064 void Parser::SkipQualIdent() {
10065 ASSERT(IsIdentifier()); 10065 ASSERT(IsIdentifier());
10066 ConsumeToken(); 10066 ConsumeToken();
10067 if (CurrentToken() == Token::kPERIOD) { 10067 if (CurrentToken() == Token::kPERIOD) {
10068 ConsumeToken(); // Consume the kPERIOD token. 10068 ConsumeToken(); // Consume the kPERIOD token.
10069 ExpectIdentifier("identifier expected after '.'"); 10069 ExpectIdentifier("identifier expected after '.'");
10070 } 10070 }
10071 } 10071 }
10072 10072
10073 } // namespace dart 10073 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/language/block_scope_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698