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

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

Issue 914303006: Fix yield statements in catch blocks (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 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/language.status » ('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 3153 matching lines...) Expand 10 before | Expand all | Expand 10 after
3164 // The closure containing the body of an async function is debuggable. 3164 // The closure containing the body of an async function is debuggable.
3165 ASSERT(func.is_debuggable()); 3165 ASSERT(func.is_debuggable());
3166 OpenAsyncClosure(); 3166 OpenAsyncClosure();
3167 } else if (func.IsSyncGenerator()) { 3167 } else if (func.IsSyncGenerator()) {
3168 // The code of a sync generator is synthesized. Disable debugging. 3168 // The code of a sync generator is synthesized. Disable debugging.
3169 func.set_is_debuggable(false); 3169 func.set_is_debuggable(false);
3170 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos()); 3170 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos());
3171 } else if (func.IsSyncGenClosure()) { 3171 } else if (func.IsSyncGenClosure()) {
3172 // The closure containing the body of a sync generator is debuggable. 3172 // The closure containing the body of a sync generator is debuggable.
3173 ASSERT(func.is_debuggable()); 3173 ASSERT(func.is_debuggable());
3174 // Nothing special to do. 3174 async_temp_scope_ = current_block_->scope;
3175 } 3175 }
3176 3176
3177 BoolScope allow_await(&this->await_is_keyword_, 3177 BoolScope allow_await(&this->await_is_keyword_,
3178 func.IsAsyncOrGenerator() || func.is_generated_body()); 3178 func.IsAsyncOrGenerator() || func.is_generated_body());
3179 intptr_t end_token_pos = 0; 3179 intptr_t end_token_pos = 0;
3180 if (CurrentToken() == Token::kLBRACE) { 3180 if (CurrentToken() == Token::kLBRACE) {
3181 ConsumeToken(); 3181 ConsumeToken();
3182 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { 3182 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) {
3183 const Class& owner = Class::Handle(Z, func.Owner()); 3183 const Class& owner = Class::Handle(Z, func.Owner());
3184 if (!owner.IsObjectClass()) { 3184 if (!owner.IsObjectClass()) {
(...skipping 2783 matching lines...) Expand 10 before | Expand all | Expand 10 after
5968 stack_trace_param.var, 5968 stack_trace_param.var,
5969 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); 5969 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
5970 current_block_->statements->Add(new(Z) InstanceCallNode( 5970 current_block_->statements->Add(new(Z) InstanceCallNode(
5971 Scanner::kNoSourcePos, 5971 Scanner::kNoSourcePos,
5972 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var), 5972 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var),
5973 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), 5973 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()),
5974 no_args)); 5974 no_args));
5975 } 5975 }
5976 5976
5977 ASSERT(try_blocks_list_ != NULL); 5977 ASSERT(try_blocks_list_ != NULL);
5978 if (innermost_function().IsAsyncClosure() || 5978 ASSERT(innermost_function().IsAsyncClosure() ||
5979 innermost_function().IsAsyncFunction()) { 5979 innermost_function().IsAsyncFunction());
5980 if ((try_blocks_list_->outer_try_block() != NULL) && 5980 if ((try_blocks_list_->outer_try_block() != NULL) &&
5981 (try_blocks_list_->outer_try_block()->try_block() 5981 (try_blocks_list_->outer_try_block()->try_block()
5982 ->scope->function_level() == 5982 ->scope->function_level() ==
5983 current_block_->scope->function_level())) { 5983 current_block_->scope->function_level())) {
5984 // We need to unchain three scope levels: catch clause, catch 5984 // We need to unchain three scope levels: catch clause, catch
5985 // parameters, and the general try block. 5985 // parameters, and the general try block.
5986 RestoreSavedTryContext( 5986 RestoreSavedTryContext(
5987 current_block_->scope->parent()->parent()->parent(), 5987 current_block_->scope->parent()->parent()->parent(),
5988 try_blocks_list_->outer_try_block()->try_index(), 5988 try_blocks_list_->outer_try_block()->try_index(),
5989 current_block_->statements); 5989 current_block_->statements);
5990 } else { 5990 } else {
5991 parsed_function()->reset_saved_try_ctx_vars(); 5991 parsed_function()->reset_saved_try_ctx_vars();
5992 }
5993 } 5992 }
5994 5993
5995 // Complete the async future with an error. 5994 // Complete the async future with an error.
5996 // Since we control the catch block there is no need to generate a nested 5995 // Since we control the catch block there is no need to generate a nested
5997 // if/then/else. 5996 // if/then/else.
5998 LocalVariable* async_completer = current_block_->scope->LookupVariable( 5997 LocalVariable* async_completer = current_block_->scope->LookupVariable(
5999 Symbols::AsyncCompleter(), false); 5998 Symbols::AsyncCompleter(), false);
6000 ASSERT(async_completer != NULL); 5999 ASSERT(async_completer != NULL);
6001 ArgumentListNode* completer_args = 6000 ArgumentListNode* completer_args =
6002 new (Z) ArgumentListNode(Scanner::kNoSourcePos); 6001 new (Z) ArgumentListNode(Scanner::kNoSourcePos);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
6074 Symbols::StackTraceVar(), 6073 Symbols::StackTraceVar(),
6075 Type::ZoneHandle(Z, Type::DynamicType())); 6074 Type::ZoneHandle(Z, Type::DynamicType()));
6076 current_block_->scope->AddVariable(stack_trace_var); 6075 current_block_->scope->AddVariable(stack_trace_var);
6077 } 6076 }
6078 6077
6079 // Open the try block. 6078 // Open the try block.
6080 OpenBlock(); 6079 OpenBlock();
6081 PushTryBlock(current_block_); 6080 PushTryBlock(current_block_);
6082 6081
6083 if (innermost_function().IsAsyncClosure() || 6082 if (innermost_function().IsAsyncClosure() ||
6084 innermost_function().IsAsyncFunction()) { 6083 innermost_function().IsAsyncFunction() ||
6084 innermost_function().IsSyncGenClosure() ||
6085 innermost_function().IsSyncGenerator()) {
6085 SetupSavedTryContext(context_var); 6086 SetupSavedTryContext(context_var);
6086 } 6087 }
6087 } 6088 }
6088 6089
6089 6090
6090 void Parser::AddSyncGenClosureParameters(ParamList* params) { 6091 void Parser::AddSyncGenClosureParameters(ParamList* params) {
6091 // Create the parameter list for the body closure of a sync generator: 6092 // Create the parameter list for the body closure of a sync generator:
6092 // 1) Implicit closure parameter; 6093 // 1) Implicit closure parameter;
6093 // 2) Iterator 6094 // 2) Iterator
6094 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); 6095 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
6157 ClassFinalizer::FinalizeType( 6158 ClassFinalizer::FinalizeType(
6158 sig_cls, sig_type, ClassFinalizer::kCanonicalize); 6159 sig_cls, sig_type, ClassFinalizer::kCanonicalize);
6159 } 6160 }
6160 ASSERT(AbstractType::Handle(Z, body.result_type()).IsResolved()); 6161 ASSERT(AbstractType::Handle(Z, body.result_type()).IsResolved());
6161 ASSERT(body.NumParameters() == closure_params.parameters->length()); 6162 ASSERT(body.NumParameters() == closure_params.parameters->length());
6162 } 6163 }
6163 6164
6164 OpenFunctionBlock(body); 6165 OpenFunctionBlock(body);
6165 AddFormalParamsToScope(&closure_params, current_block_->scope); 6166 AddFormalParamsToScope(&closure_params, current_block_->scope);
6166 OpenBlock(); 6167 OpenBlock();
6167 6168 async_temp_scope_ = current_block_->scope;
6168 /*
6169 async_temp_scope_ = current_block_->scope; // Is this needed?
6170 */
6171 return body.raw(); 6169 return body.raw();
6172 } 6170 }
6173 6171
6174 SequenceNode* Parser::CloseSyncGenFunction(const Function& closure, 6172 SequenceNode* Parser::CloseSyncGenFunction(const Function& closure,
6175 SequenceNode* closure_body) { 6173 SequenceNode* closure_body) {
6176 // The block for the closure body has already been closed. Close the 6174 // The block for the closure body has already been closed. Close the
6177 // corresponding function block. 6175 // corresponding function block.
6178 CloseBlock(); 6176 CloseBlock();
6179 6177
6180 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); 6178 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
(...skipping 2008 matching lines...) Expand 10 before | Expand all | Expand 10 after
8189 8187
8190 SequenceNode* Parser::ParseFinallyBlock() { 8188 SequenceNode* Parser::ParseFinallyBlock() {
8191 TRACE_PARSER("ParseFinallyBlock"); 8189 TRACE_PARSER("ParseFinallyBlock");
8192 OpenBlock(); 8190 OpenBlock();
8193 ExpectToken(Token::kLBRACE); 8191 ExpectToken(Token::kLBRACE);
8194 8192
8195 // In case of async closures we need to restore the saved try index of an 8193 // In case of async closures we need to restore the saved try index of an
8196 // outer try block (if it exists). The current try block has already been 8194 // outer try block (if it exists). The current try block has already been
8197 // removed from the stack of try blocks. 8195 // removed from the stack of try blocks.
8198 if ((innermost_function().IsAsyncClosure() || 8196 if ((innermost_function().IsAsyncClosure() ||
8199 innermost_function().IsAsyncFunction()) && 8197 innermost_function().IsAsyncFunction() ||
8198 innermost_function().IsSyncGenClosure() ||
8199 innermost_function().IsSyncGenerator()) &&
8200 (try_blocks_list_ != NULL)) { 8200 (try_blocks_list_ != NULL)) {
8201 // We need two unchain two scopes: finally clause, and the try block level. 8201 // We need two unchain two scopes: finally clause, and the try block level.
8202 RestoreSavedTryContext(current_block_->scope->parent()->parent(), 8202 RestoreSavedTryContext(current_block_->scope->parent()->parent(),
8203 try_blocks_list_->try_index(), 8203 try_blocks_list_->try_index(),
8204 current_block_->statements); 8204 current_block_->statements);
8205 } else { 8205 } else {
8206 parsed_function()->reset_saved_try_ctx_vars(); 8206 parsed_function()->reset_saved_try_ctx_vars();
8207 } 8207 }
8208 8208
8209 ParseStatementSequence(); 8209 ParseStatementSequence();
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
8349 } 8349 }
8350 8350
8351 // Add nested block with user-defined code. This blocks allows 8351 // Add nested block with user-defined code. This blocks allows
8352 // declarations in the body to shadow the catch parameters. 8352 // declarations in the body to shadow the catch parameters.
8353 CheckToken(Token::kLBRACE); 8353 CheckToken(Token::kLBRACE);
8354 8354
8355 // In case of async closures we need to restore the saved try index of an 8355 // In case of async closures we need to restore the saved try index of an
8356 // outer try block (if it exists). 8356 // outer try block (if it exists).
8357 ASSERT(try_blocks_list_ != NULL); 8357 ASSERT(try_blocks_list_ != NULL);
8358 if (innermost_function().IsAsyncClosure() || 8358 if (innermost_function().IsAsyncClosure() ||
8359 innermost_function().IsAsyncFunction()) { 8359 innermost_function().IsAsyncFunction() ||
8360 innermost_function().IsSyncGenClosure() ||
8361 innermost_function().IsSyncGenerator()) {
8360 if ((try_blocks_list_->outer_try_block() != NULL) && 8362 if ((try_blocks_list_->outer_try_block() != NULL) &&
8361 (try_blocks_list_->outer_try_block()->try_block() 8363 (try_blocks_list_->outer_try_block()->try_block()
8362 ->scope->function_level() == 8364 ->scope->function_level() ==
8363 current_block_->scope->function_level())) { 8365 current_block_->scope->function_level())) {
8364 // We need to unchain three scope levels: catch clause, catch 8366 // We need to unchain three scope levels: catch clause, catch
8365 // parameters, and the general try block. 8367 // parameters, and the general try block.
8366 RestoreSavedTryContext( 8368 RestoreSavedTryContext(
8367 current_block_->scope->parent()->parent()->parent(), 8369 current_block_->scope->parent()->parent()->parent(),
8368 try_blocks_list_->outer_try_block()->try_index(), 8370 try_blocks_list_->outer_try_block()->try_index(),
8369 current_block_->statements); 8371 current_block_->statements);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
8457 // a rethrow, use an empty else body (current = NULL above). 8459 // a rethrow, use an empty else body (current = NULL above).
8458 8460
8459 while (!type_tests.is_empty()) { 8461 while (!type_tests.is_empty()) {
8460 AstNode* type_test = type_tests.RemoveLast(); 8462 AstNode* type_test = type_tests.RemoveLast();
8461 SequenceNode* catch_block = catch_blocks.RemoveLast(); 8463 SequenceNode* catch_block = catch_blocks.RemoveLast();
8462 8464
8463 // In case of async closures we need to restore the saved try index of an 8465 // In case of async closures we need to restore the saved try index of an
8464 // outer try block (if it exists). 8466 // outer try block (if it exists).
8465 ASSERT(try_blocks_list_ != NULL); 8467 ASSERT(try_blocks_list_ != NULL);
8466 if (innermost_function().IsAsyncClosure() || 8468 if (innermost_function().IsAsyncClosure() ||
8467 innermost_function().IsAsyncFunction()) { 8469 innermost_function().IsAsyncFunction() ||
8470 innermost_function().IsSyncGenClosure() ||
8471 innermost_function().IsSyncGenerator()) {
8468 if ((try_blocks_list_->outer_try_block() != NULL) && 8472 if ((try_blocks_list_->outer_try_block() != NULL) &&
8469 (try_blocks_list_->outer_try_block()->try_block() 8473 (try_blocks_list_->outer_try_block()->try_block()
8470 ->scope->function_level() == 8474 ->scope->function_level() ==
8471 current_block_->scope->function_level())) { 8475 current_block_->scope->function_level())) {
8472 // We need to unchain three scope levels: catch clause, catch 8476 // We need to unchain three scope levels: catch clause, catch
8473 // parameters, and the general try block. 8477 // parameters, and the general try block.
8474 RestoreSavedTryContext( 8478 RestoreSavedTryContext(
8475 current_block_->scope->parent()->parent(), 8479 current_block_->scope->parent()->parent(),
8476 try_blocks_list_->outer_try_block()->try_index(), 8480 try_blocks_list_->outer_try_block()->try_index(),
8477 current_block_->statements); 8481 current_block_->statements);
(...skipping 10 matching lines...) Expand all
8488 } 8492 }
8489 8493
8490 8494
8491 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) { 8495 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) {
8492 const String& async_saved_try_ctx_name = 8496 const String& async_saved_try_ctx_name =
8493 BuildAsyncSavedTryContextName(Z, last_used_try_index_ - 1); 8497 BuildAsyncSavedTryContextName(Z, last_used_try_index_ - 1);
8494 LocalVariable* async_saved_try_ctx = new (Z) LocalVariable( 8498 LocalVariable* async_saved_try_ctx = new (Z) LocalVariable(
8495 Scanner::kNoSourcePos, 8499 Scanner::kNoSourcePos,
8496 async_saved_try_ctx_name, 8500 async_saved_try_ctx_name,
8497 Type::ZoneHandle(Z, Type::DynamicType())); 8501 Type::ZoneHandle(Z, Type::DynamicType()));
8502 ASSERT(async_temp_scope_ != NULL);
8498 async_temp_scope_->AddVariable(async_saved_try_ctx); 8503 async_temp_scope_->AddVariable(async_saved_try_ctx);
8499 async_saved_try_ctx->set_is_captured(); 8504 async_saved_try_ctx->set_is_captured();
8500 async_saved_try_ctx = current_block_->scope->LookupVariable( 8505 async_saved_try_ctx = current_block_->scope->LookupVariable(
8501 async_saved_try_ctx_name, false); 8506 async_saved_try_ctx_name, false);
8502 ASSERT(async_saved_try_ctx != NULL); 8507 ASSERT(async_saved_try_ctx != NULL);
8503 ASSERT(saved_try_context != NULL); 8508 ASSERT(saved_try_context != NULL);
8504 current_block_->statements->Add(new(Z) StoreLocalNode( 8509 current_block_->statements->Add(new(Z) StoreLocalNode(
8505 Scanner::kNoSourcePos, 8510 Scanner::kNoSourcePos,
8506 async_saved_try_ctx, 8511 async_saved_try_ctx,
8507 new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context))); 8512 new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context)));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
8593 OpenBlock(); 8598 OpenBlock();
8594 current_block_->scope->AddLabel(try_label); 8599 current_block_->scope->AddLabel(try_label);
8595 } 8600 }
8596 8601
8597 // Now parse the 'try' block. 8602 // Now parse the 'try' block.
8598 OpenBlock(); 8603 OpenBlock();
8599 PushTryBlock(current_block_); 8604 PushTryBlock(current_block_);
8600 ExpectToken(Token::kLBRACE); 8605 ExpectToken(Token::kLBRACE);
8601 8606
8602 if (innermost_function().IsAsyncClosure() || 8607 if (innermost_function().IsAsyncClosure() ||
8603 innermost_function().IsAsyncFunction()) { 8608 innermost_function().IsAsyncFunction() ||
8609 innermost_function().IsSyncGenClosure() ||
8610 innermost_function().IsSyncGenerator()) {
8604 SetupSavedTryContext(context_var); 8611 SetupSavedTryContext(context_var);
8605 } 8612 }
8606 8613
8607 ParseStatementSequence(); 8614 ParseStatementSequence();
8608 ExpectToken(Token::kRBRACE); 8615 ExpectToken(Token::kRBRACE);
8609 SequenceNode* try_block = CloseBlock(); 8616 SequenceNode* try_block = CloseBlock();
8610 8617
8611 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && 8618 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") &&
8612 (CurrentToken() != Token::kFINALLY)) { 8619 (CurrentToken() != Token::kFINALLY)) {
8613 ReportError("catch or finally clause expected"); 8620 ReportError("catch or finally clause expected");
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
8835 yield->AddNode(set_is_yield_each); 8842 yield->AddNode(set_is_yield_each);
8836 } 8843 }
8837 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); 8844 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
8838 await_marker->set_scope(current_block_->scope); 8845 await_marker->set_scope(current_block_->scope);
8839 yield->AddNode(await_marker); 8846 yield->AddNode(await_marker);
8840 // Return true to indicate that a value has been generated. 8847 // Return true to indicate that a value has been generated.
8841 ReturnNode* return_true = new(Z) ReturnNode(statement_pos, 8848 ReturnNode* return_true = new(Z) ReturnNode(statement_pos,
8842 new(Z) LiteralNode(TokenPos(), Bool::True())); 8849 new(Z) LiteralNode(TokenPos(), Bool::True()));
8843 return_true->set_return_type(ReturnNode::kContinuationTarget); 8850 return_true->set_return_type(ReturnNode::kContinuationTarget);
8844 yield->AddNode(return_true); 8851 yield->AddNode(return_true);
8852
8853 // If this expression is part of a try block, also append the code for
8854 // restoring the saved try context that lives on the stack.
8855 const String& async_saved_try_ctx_name =
8856 String::Handle(Z, parsed_function()->async_saved_try_ctx_name());
8857 if (!async_saved_try_ctx_name.IsNull()) {
8858 LocalVariable* async_saved_try_ctx =
8859 current_block_->scope->LookupVariable(async_saved_try_ctx_name,
8860 false);
8861 ASSERT(async_saved_try_ctx != NULL);
8862 yield->AddNode(new (Z) StoreLocalNode(
8863 Scanner::kNoSourcePos,
8864 parsed_function()->saved_try_ctx(),
8865 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
8866 }
8867
8845 statement = yield; 8868 statement = yield;
8846 ExpectSemicolon(); 8869 ExpectSemicolon();
8847 } else if (token == Token::kIF) { 8870 } else if (token == Token::kIF) {
8848 statement = ParseIfStatement(label_name); 8871 statement = ParseIfStatement(label_name);
8849 } else if (token == Token::kASSERT) { 8872 } else if (token == Token::kASSERT) {
8850 statement = ParseAssertStatement(); 8873 statement = ParseAssertStatement();
8851 ExpectSemicolon(); 8874 ExpectSemicolon();
8852 } else if (IsVariableDeclaration()) { 8875 } else if (IsVariableDeclaration()) {
8853 statement = ParseVariableDeclarationList(); 8876 statement = ParseVariableDeclarationList();
8854 ExpectSemicolon(); 8877 ExpectSemicolon();
(...skipping 3669 matching lines...) Expand 10 before | Expand all | Expand 10 after
12524 void Parser::SkipQualIdent() { 12547 void Parser::SkipQualIdent() {
12525 ASSERT(IsIdentifier()); 12548 ASSERT(IsIdentifier());
12526 ConsumeToken(); 12549 ConsumeToken();
12527 if (CurrentToken() == Token::kPERIOD) { 12550 if (CurrentToken() == Token::kPERIOD) {
12528 ConsumeToken(); // Consume the kPERIOD token. 12551 ConsumeToken(); // Consume the kPERIOD token.
12529 ExpectIdentifier("identifier expected after '.'"); 12552 ExpectIdentifier("identifier expected after '.'");
12530 } 12553 }
12531 } 12554 }
12532 12555
12533 } // namespace dart 12556 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698