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

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

Issue 538803002: Enable await in for and for-in loops. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 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 | « runtime/vm/parser.h ('k') | tests/language/await_future_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 "platform/utils.h" 8 #include "platform/utils.h"
9 #include "vm/ast_transformer.h" 9 #include "vm/ast_transformer.h"
10 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
(...skipping 5917 matching lines...) Expand 10 before | Expand all | Expand 10 after
5928 AstNode* Parser::CallGetter(intptr_t token_pos, 5928 AstNode* Parser::CallGetter(intptr_t token_pos,
5929 AstNode* object, 5929 AstNode* object,
5930 const String& name) { 5930 const String& name) {
5931 return new(I) InstanceGetterNode(token_pos, object, name); 5931 return new(I) InstanceGetterNode(token_pos, object, name);
5932 } 5932 }
5933 5933
5934 5934
5935 // Returns ast nodes of the variable initialization. 5935 // Returns ast nodes of the variable initialization.
5936 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, 5936 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type,
5937 bool is_final, 5937 bool is_final,
5938 bool is_const) { 5938 bool is_const,
5939 SequenceNode** await_preamble) {
5939 TRACE_PARSER("ParseVariableDeclaration"); 5940 TRACE_PARSER("ParseVariableDeclaration");
5940 ASSERT(IsIdentifier()); 5941 ASSERT(IsIdentifier());
5941 const intptr_t ident_pos = TokenPos(); 5942 const intptr_t ident_pos = TokenPos();
5942 const String& ident = *CurrentLiteral(); 5943 const String& ident = *CurrentLiteral();
5943 LocalVariable* variable = new(I) LocalVariable( 5944 LocalVariable* variable = new(I) LocalVariable(
5944 ident_pos, ident, type); 5945 ident_pos, ident, type);
5945 ConsumeToken(); // Variable identifier. 5946 ConsumeToken(); // Variable identifier.
5946 AstNode* initialization = NULL; 5947 AstNode* initialization = NULL;
5947 if (CurrentToken() == Token::kASSIGN) { 5948 if (CurrentToken() == Token::kASSIGN) {
5948 // Variable initialization. 5949 // Variable initialization.
5949 const intptr_t assign_pos = TokenPos(); 5950 const intptr_t assign_pos = TokenPos();
5950 ConsumeToken(); 5951 ConsumeToken();
5951 AstNode* expr = ParseAwaitableExpr(is_const, kConsumeCascades, NULL); 5952 AstNode* expr = ParseAwaitableExpr(
5953 is_const, kConsumeCascades, await_preamble);
5952 initialization = new(I) StoreLocalNode( 5954 initialization = new(I) StoreLocalNode(
5953 assign_pos, variable, expr); 5955 assign_pos, variable, expr);
5954 if (is_const) { 5956 if (is_const) {
5955 ASSERT(expr->IsLiteralNode()); 5957 ASSERT(expr->IsLiteralNode());
5956 variable->SetConstValue(expr->AsLiteralNode()->literal()); 5958 variable->SetConstValue(expr->AsLiteralNode()->literal());
5957 } 5959 }
5958 } else if (is_final || is_const) { 5960 } else if (is_final || is_const) {
5959 ReportError(ident_pos, 5961 ReportError(ident_pos,
5960 "missing initialization of 'final' or 'const' variable"); 5962 "missing initialization of 'final' or 'const' variable");
5961 } else { 5963 } else {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
6054 SkipMetadata(); 6056 SkipMetadata();
6055 bool is_final = (CurrentToken() == Token::kFINAL); 6057 bool is_final = (CurrentToken() == Token::kFINAL);
6056 bool is_const = (CurrentToken() == Token::kCONST); 6058 bool is_const = (CurrentToken() == Token::kCONST);
6057 const AbstractType& type = AbstractType::ZoneHandle(I, 6059 const AbstractType& type = AbstractType::ZoneHandle(I,
6058 ParseConstFinalVarOrType(FLAG_enable_type_checks ? 6060 ParseConstFinalVarOrType(FLAG_enable_type_checks ?
6059 ClassFinalizer::kCanonicalize : ClassFinalizer::kIgnore)); 6061 ClassFinalizer::kCanonicalize : ClassFinalizer::kIgnore));
6060 if (!IsIdentifier()) { 6062 if (!IsIdentifier()) {
6061 ReportError("identifier expected"); 6063 ReportError("identifier expected");
6062 } 6064 }
6063 6065
6064 AstNode* initializers = ParseVariableDeclaration(type, is_final, is_const); 6066 SequenceNode* preamble = NULL;
6067 AstNode* initializers =
6068 ParseVariableDeclaration(type, is_final, is_const, &preamble);
6065 ASSERT(initializers != NULL); 6069 ASSERT(initializers != NULL);
6070 if (preamble != NULL) {
hausner 2014/09/04 16:30:58 I don't understand this. If preamble is not NULL,
Michael Lippautz (Google) 2014/09/04 17:07:38 There's no need anymore as this was a leftover. Do
6071 SequenceNode* sequence = NodeAsSequenceNode(initializers->token_pos(),
6072 preamble,
6073 NULL);
6074 sequence->Add(initializers);
6075 initializers = sequence;
6076 }
6066 while (CurrentToken() == Token::kCOMMA) { 6077 while (CurrentToken() == Token::kCOMMA) {
6067 ConsumeToken(); 6078 ConsumeToken();
6068 if (!IsIdentifier()) { 6079 if (!IsIdentifier()) {
6069 ReportError("identifier expected after comma"); 6080 ReportError("identifier expected after comma");
6070 } 6081 }
6071 // We have a second initializer. Allocate a sequence node now. 6082 // We have a second initializer. Allocate a sequence node now.
6072 // The sequence does not own the current scope. Set its own scope to NULL. 6083 // The sequence does not own the current scope. Set its own scope to NULL.
6073 SequenceNode* sequence = NodeAsSequenceNode(initializers->token_pos(), 6084 SequenceNode* sequence = NodeAsSequenceNode(initializers->token_pos(),
6074 initializers, 6085 initializers,
6075 NULL); 6086 NULL);
6076 sequence->Add(ParseVariableDeclaration(type, is_final, is_const)); 6087 preamble = NULL;
6088 AstNode* declaration = ParseVariableDeclaration(
6089 type, is_final, is_const, &preamble);
6090 if (preamble != NULL) {
6091 sequence->Add(preamble);
6092 }
6093 sequence->Add(declaration);
6077 initializers = sequence; 6094 initializers = sequence;
6078 } 6095 }
6079 return initializers; 6096 return initializers;
6080 } 6097 }
6081 6098
6082 6099
6083 AstNode* Parser::ParseFunctionStatement(bool is_literal) { 6100 AstNode* Parser::ParseFunctionStatement(bool is_literal) {
6084 TRACE_PARSER("ParseFunctionStatement"); 6101 TRACE_PARSER("ParseFunctionStatement");
6085 AbstractType& result_type = AbstractType::Handle(I); 6102 AbstractType& result_type = AbstractType::Handle(I);
6086 const String* variable_name = NULL; 6103 const String* variable_name = NULL;
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after
7028 ClassFinalizer::kIgnore)); 7045 ClassFinalizer::kIgnore));
7029 loop_var_pos = TokenPos(); 7046 loop_var_pos = TokenPos();
7030 loop_var_name = ExpectIdentifier("variable name expected"); 7047 loop_var_name = ExpectIdentifier("variable name expected");
7031 loop_var = new(I) LocalVariable(loop_var_pos, *loop_var_name, type); 7048 loop_var = new(I) LocalVariable(loop_var_pos, *loop_var_name, type);
7032 if (is_final) { 7049 if (is_final) {
7033 loop_var->set_is_final(); 7050 loop_var->set_is_final();
7034 } 7051 }
7035 } 7052 }
7036 ExpectToken(Token::kIN); 7053 ExpectToken(Token::kIN);
7037 const intptr_t collection_pos = TokenPos(); 7054 const intptr_t collection_pos = TokenPos();
7038 AstNode* collection_expr = ParseExpr(kAllowConst, kConsumeCascades); 7055 AstNode* collection_expr =
7056 ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
7039 ExpectToken(Token::kRPAREN); 7057 ExpectToken(Token::kRPAREN);
7040 7058
7041 OpenBlock(); // Implicit block around while loop. 7059 OpenBlock(); // Implicit block around while loop.
7042 7060
7043 // Generate implicit iterator variable and add to scope. 7061 // Generate implicit iterator variable and add to scope.
7044 // We could set the type of the implicit iterator variable to Iterator<T> 7062 // We could set the type of the implicit iterator variable to Iterator<T>
7045 // where T is the type of the for loop variable. However, the type error 7063 // where T is the type of the for loop variable. However, the type error
7046 // would refer to the compiler generated iterator and could confuse the user. 7064 // would refer to the compiler generated iterator and could confuse the user.
7047 // It is better to leave the iterator untyped and postpone the type error 7065 // It is better to leave the iterator untyped and postpone the type error
7048 // until the loop variable is assigned to. 7066 // until the loop variable is assigned to.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
7129 // Open a block that contains the loop variable. Make it a loop block so 7147 // Open a block that contains the loop variable. Make it a loop block so
7130 // that we allocate a new context if the loop variable is captured. 7148 // that we allocate a new context if the loop variable is captured.
7131 OpenLoopBlock(); 7149 OpenLoopBlock();
7132 AstNode* initializer = NULL; 7150 AstNode* initializer = NULL;
7133 const intptr_t init_pos = TokenPos(); 7151 const intptr_t init_pos = TokenPos();
7134 LocalScope* init_scope = current_block_->scope; 7152 LocalScope* init_scope = current_block_->scope;
7135 if (CurrentToken() != Token::kSEMICOLON) { 7153 if (CurrentToken() != Token::kSEMICOLON) {
7136 if (IsVariableDeclaration()) { 7154 if (IsVariableDeclaration()) {
7137 initializer = ParseVariableDeclarationList(); 7155 initializer = ParseVariableDeclarationList();
7138 } else { 7156 } else {
7139 initializer = ParseExpr(kAllowConst, kConsumeCascades); 7157 initializer = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
7140 } 7158 }
7141 } 7159 }
7142 ExpectSemicolon(); 7160 ExpectSemicolon();
7143 AstNode* condition = NULL; 7161 AstNode* condition = NULL;
7162 SequenceNode* condition_preamble = NULL;
7144 if (CurrentToken() != Token::kSEMICOLON) { 7163 if (CurrentToken() != Token::kSEMICOLON) {
7145 condition = ParseExpr(kAllowConst, kConsumeCascades); 7164 condition = ParseAwaitableExpr(
7165 kAllowConst, kConsumeCascades, &condition_preamble);
7146 } 7166 }
7147 ExpectSemicolon(); 7167 ExpectSemicolon();
7148 AstNode* increment = NULL; 7168 AstNode* increment = NULL;
7149 const intptr_t incr_pos = TokenPos(); 7169 const intptr_t incr_pos = TokenPos();
7150 if (CurrentToken() != Token::kRPAREN) { 7170 if (CurrentToken() != Token::kRPAREN) {
7151 increment = ParseExprList(); 7171 increment = ParseAwaitableExprList();
7152 } 7172 }
7153 ExpectToken(Token::kRPAREN); 7173 ExpectToken(Token::kRPAREN);
7154 const bool parsing_loop_body = true; 7174 const bool parsing_loop_body = true;
7155 SequenceNode* body = ParseNestedStatement(parsing_loop_body, label); 7175 SequenceNode* body = ParseNestedStatement(parsing_loop_body, label);
7156 7176
7157 // Check whether any of the variables in the initializer part of 7177 // Check whether any of the variables in the initializer part of
7158 // the for statement are captured by a closure. If so, we insert a 7178 // the for statement are captured by a closure. If so, we insert a
7159 // node that creates a new Context for the loop variable before 7179 // node that creates a new Context for the loop variable before
7160 // the increment expression is evaluated. 7180 // the increment expression is evaluated.
7161 for (int i = 0; i < init_scope->num_variables(); i++) { 7181 for (int i = 0; i < init_scope->num_variables(); i++) {
7162 if (init_scope->VariableAt(i)->is_captured() && 7182 if (init_scope->VariableAt(i)->is_captured() &&
7163 (init_scope->VariableAt(i)->owner() == init_scope)) { 7183 (init_scope->VariableAt(i)->owner() == init_scope)) {
7164 SequenceNode* incr_sequence = new(I) SequenceNode(incr_pos, NULL); 7184 SequenceNode* incr_sequence = new(I) SequenceNode(incr_pos, NULL);
7165 incr_sequence->Add(new(I) CloneContextNode(for_pos)); 7185 incr_sequence->Add(new(I) CloneContextNode(for_pos));
7166 if (increment != NULL) { 7186 if (increment != NULL) {
7167 incr_sequence->Add(increment); 7187 incr_sequence->Add(increment);
7168 } 7188 }
7169 increment = incr_sequence; 7189 increment = incr_sequence;
7170 break; 7190 break;
7171 } 7191 }
7172 } 7192 }
7173 AstNode* for_node = new(I) ForNode( 7193 AstNode* for_node = new(I) ForNode(
7174 for_pos, 7194 for_pos,
7175 label, 7195 label,
7176 NodeAsSequenceNode(init_pos, initializer, NULL), 7196 NodeAsSequenceNode(init_pos, initializer, NULL),
7177 condition, 7197 condition,
7198 condition_preamble,
7178 NodeAsSequenceNode(incr_pos, increment, NULL), 7199 NodeAsSequenceNode(incr_pos, increment, NULL),
7179 body); 7200 body);
7180 current_block_->statements->Add(for_node); 7201 current_block_->statements->Add(for_node);
7181 return CloseBlock(); 7202 return CloseBlock();
7182 } 7203 }
7183 7204
7184 7205
7185 // Calling VM-internal helpers, uses implementation core library. 7206 // Calling VM-internal helpers, uses implementation core library.
7186 AstNode* Parser::MakeStaticCall(const String& cls_name, 7207 AstNode* Parser::MakeStaticCall(const String& cls_name,
7187 const String& func_name, 7208 const String& func_name,
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after
8255 left_operand = OptimizeBinaryOpNode( 8276 left_operand = OptimizeBinaryOpNode(
8256 op_pos, op_kind, left_operand, right_operand); 8277 op_pos, op_kind, left_operand, right_operand);
8257 } 8278 }
8258 } 8279 }
8259 current_preced--; 8280 current_preced--;
8260 } 8281 }
8261 return left_operand; 8282 return left_operand;
8262 } 8283 }
8263 8284
8264 8285
8265 AstNode* Parser::ParseExprList() { 8286 AstNode* Parser::ParseAwaitableExprList() {
8266 TRACE_PARSER("ParseExprList"); 8287 TRACE_PARSER("ParseAwaitableExprList");
8267 AstNode* expressions = ParseExpr(kAllowConst, kConsumeCascades); 8288 SequenceNode* preamble = NULL;
8289 AstNode* expressions = ParseAwaitableExpr(
8290 kAllowConst, kConsumeCascades, &preamble);
8291 if (preamble != NULL) {
hausner 2014/09/04 16:30:58 Ditto.
Michael Lippautz (Google) 2014/09/04 17:07:38 Done.
8292 SequenceNode* sequence = NodeAsSequenceNode(
8293 expressions->token_pos(), preamble, NULL);
8294 sequence->Add(expressions);
8295 expressions = sequence;
8296 }
8268 if (CurrentToken() == Token::kCOMMA) { 8297 if (CurrentToken() == Token::kCOMMA) {
8269 // Collect comma-separated expressions in a non scope owning sequence node. 8298 // Collect comma-separated expressions in a non scope owning sequence node.
8270 SequenceNode* list = new(I) SequenceNode(TokenPos(), NULL); 8299 SequenceNode* list = new(I) SequenceNode(TokenPos(), NULL);
8271 list->Add(expressions); 8300 list->Add(expressions);
8272 while (CurrentToken() == Token::kCOMMA) { 8301 while (CurrentToken() == Token::kCOMMA) {
8273 ConsumeToken(); 8302 ConsumeToken();
8274 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); 8303 preamble = NULL;
8304 AstNode* expr = ParseAwaitableExpr(
8305 kAllowConst, kConsumeCascades, &preamble);
8306 if (preamble != NULL) {
8307 list->Add(preamble);
8308 }
8275 list->Add(expr); 8309 list->Add(expr);
8276 } 8310 }
8277 expressions = list; 8311 expressions = list;
8278 } 8312 }
8279 return expressions; 8313 return expressions;
8280 } 8314 }
8281 8315
8282 8316
8283 void Parser::EnsureExpressionTemp() { 8317 void Parser::EnsureExpressionTemp() {
8284 // Temporary used later by the flow_graph_builder. 8318 // Temporary used later by the flow_graph_builder.
(...skipping 3255 matching lines...) Expand 10 before | Expand all | Expand 10 after
11540 void Parser::SkipQualIdent() { 11574 void Parser::SkipQualIdent() {
11541 ASSERT(IsIdentifier()); 11575 ASSERT(IsIdentifier());
11542 ConsumeToken(); 11576 ConsumeToken();
11543 if (CurrentToken() == Token::kPERIOD) { 11577 if (CurrentToken() == Token::kPERIOD) {
11544 ConsumeToken(); // Consume the kPERIOD token. 11578 ConsumeToken(); // Consume the kPERIOD token.
11545 ExpectIdentifier("identifier expected after '.'"); 11579 ExpectIdentifier("identifier expected after '.'");
11546 } 11580 }
11547 } 11581 }
11548 11582
11549 } // namespace dart 11583 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/await_future_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698